プログラミングの基礎概念
2.1 コード内のクライアントとサーバー
ネットワーク通信だけでなく、コード内の相互作用にもクライアント/サーバー関係が存在します。あるオブジェクトが別のオブジェクトのメソッドを呼び出す場合、呼び出し元がクライアント、呼び出される側がサーバーとみなせます。
class Calculator {
public int Add(int x, int y) {
return x + y;
}
}
class App {
static void Main() {
Calculator calc = new Calculator();
int sum = calc.Add(5, 3); // calcがサーバー、Appがクライアント
}
}
2.2 スレッドとメソッドの関係
1つのスレッドが複数メソッドを実行でき、1つのメソッドが複数スレッドから呼び出せます。スレッドセーフでないリソースにアクセスする場合は注意が必要です。
class TaskRunner {
static void ExecuteTask() {
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
}
static void Main() {
new Thread(ExecuteTask).Start();
new Thread(ExecuteTask).Start();
}
}
2.3 呼び出しスレッドと現在スレッド
メソッドを呼び出すスレッドが「呼び出しスレッド」、メソッドが実際に実行されるスレッドが「現在スレッド」です。
2.4 ブロッキングとノンブロッキング処理
処理が完了するまで呼び出し元をブロックするメソッドをブロッキング、即座に制御を返すメソッドをノンブロッキングと呼びます。
// ブロッキング例
void LongRunningTask() {
Thread.Sleep(5000);
}
// ノンブロッキング例
async Task LongRunningTaskAsync() {
await Task.Delay(5000);
}
2.5 UIスレッドの特性
UIスレッドはメッセージループを持ち、ユーザー入力や描画処理を担当します。UIコントロールへのアクセスは原則UIスレッドからのみ可能です。
2.6 アトミック操作
中断されずに実行される不可分な操作です。単純な値型の代入はアトミックですが、複合操作は一般的に非アトミックです。
2.7 スレッドセーフ
複数スレッドから同時アクセスされても問題が起きないコードをスレッドセーフと呼びます。ロック機構で実現します。
class ThreadSafeCounter {
private int _count = 0;
private readonly object _lock = new object();
public void Increment() {
lock(_lock) {
_count++;
}
}
}
2.8 コールバックの仕組み
システムが開発者のコードを呼び出す仕組みで、デリゲートやイベントで実装されます。
2.9 マネージド/アンマネージドリソース
CLRが管理するリソースがマネージド、OSリソースなどがアンマネージドです。アンマネージドリソースは明示的な解放が必要です。
2.10 フレームワークとライブラリ
フレームワークはアプリケーションの骨格を提供し、制御の反転が特徴です。ライブラリは特定機能を提供する再利用可能なコード集です。
2.11 オブジェクト指向とコンポーネント指向
オブジェクト指向は継承と多態性を特徴とし、コンポーネント指向はバイナリレベルでの再利用を可能にします。
2.12 インターフェースの役割
システム間の相互作用を可能にする契約で、メソッドシグネチャやWeb APIなど様々な形態があります。
2.13 プロトコルの重要性
通信やデータ交換における規則で、双方が同じプロトコルに従う必要があります。
// カスタムプロトコル例
struct Message {
public byte Type;
public int Length;
public byte[] Data;
}
理解度チェック
- スレッドセーフなコレクションクラスを実装してください
- UIスレッドとワーカースレッドの違いを説明してください
- アンマネージドリソースを適切に解放する方法を説明してください