私はまだ.net 4.5のスレッドモデル(または一般的なスレッド)にかなり慣れていません。一連の同様のタスクをマルチスレッド化するためのフレームワークを実装するために、一連の抽象クラスを構築しようとしています。ルールは、入力の最初の行がセット内の問題の数を示し、次の行に各問題の入力が含まれていることです。セットを構成する入力の行数は、タスクごとに異なる場合がありますが、通常、特定の種類の問題では一貫しています。各問題は、出力として 1 行のテキストを持つことです。
目標は、これらのクラスから継承できるようにすることであり、CreateWorker メソッドと DoWork メソッドの実装についてのみ心配する必要があります。UI は ProcessInput を呼び出して処理を開始し、WriteOutput を呼び出して結果を一覧表示します。
私がこれまでに持っている基本的なテンプレートは次のとおりです。
public abstract class Wrapper
{
protected int N;
protected WorkerBase[] ProblemSet;
protected List<Task> Tasks;
public virtual void ProcessInput(TextReader input)
{
string Line = input.ReadLine();
N = int.Parse(Line);
ProblemSet = new WorkerBase[N];
Tasks= new List<Task>(N);
for (int index = 0; index < N; index++)
{
WorkerBase T = CreateWorker(input);
Tasks.Add(T.DoWorkAsync());
ProblemSet[index] = T;
}
}
public virtual bool WriteOutput(TextWriter outputStream, int timeout)
{
bool Complete = Task.WaitAll(Tasks.ToArray(), timeout);
for (int index = 0; index < N; index++)
{
outputStream.WriteLine(ProblemSet[index].Result);
}
return Complete;
}
protected abstract WorkerBase CreateWorker(TextReader inputStream);
protected abstract class WorkerBase
{
public string Result
{
get;
protected set;
}
protected abstract void DoWork();
public Task DoWorkAsync()
{
return Task.Run(() => DoWork());
}
}
}
現状では、これは私の要件を満たしています。しかし今、すべてのスレッドを停止できるアボート機能を Wrapper クラスに追加したいと考えています。問題は、キャンセル ボタンがクリックされた場合に UI がプロセスを中止できるように、中止機能をこの構造に組み込むにはどうすればよいかということです。できれば、DoWork 実装で余分なコードを記述する必要はありません。
タスクを中止するためにキャンセル トークンを渡すパターンを見つけましたが、見つかったすべてのバージョンで、DoWork がトークンの状態をチェックし、それ自体を中止する必要があります。メソッドの外部から DoWork を中止する方法が本当に必要です。