そのようなメソッドを含むライブラリを作成したとします:
Task MyLibraryMethodAsync()
{
var taskCompletionSource = new TaskCompletionSource<object>();
Action myWorkItem =
() =>
{
// Simulate some work.
// Actual work items depend on input params.
Thread.Sleep(TimeSpan.FromSeconds(1));
taskCompletionSource.SetResult(null);
};
// The next two lines is simplification for demonstration.
// I do not have access to the workerThread - it is created
// and managed for me by another lib.
// All I can do - is to post some short work items to it.
var workerThread = new Thread(new ThreadStart(myWorkItem));
workerThread.Start();
return taskCompletionSource.Task;
}
私のlibのすべてのユーザーは、MyLibraryMethodAsync
このように呼び出すことができます
await MyLibraryMethodAsync().ConfigureAwait(false);
VeryLongRunningMethod();
void VeryLongRunningMethod()
{
Thread.Sleep(TimeSpan.FromHours(1));
}
ここで問題が発生します。呼び出しVeryLongRunningMethod
内で実行されるため、長時間taskCompletionSource.SetResult(null)
ブロックされます。これは、コード (作業項目) の小さな部分を実行することを目的としているため、望ましくない動作です。workerThread
workerThread
コンテキスト/スケジューラを、返されたタスク内のスレッド プールに置き換えて、スレッド プールではなくスレッド プールawait x.ConfigureAwait(false)
で続行するにはどうすればよいですか?workerThread
私が見つけた現在の解決策は
Task MyLibraryMethodAsync()
{
// ...
return taskCompletionSource.Task
.ContinueWith(x => x.Result, TaskScheduler.Default);
}
ただし、オーバーヘッドが発生するため、好きではありません。よりエレガントなソリューションが存在する可能性がありますか?