Task.Factory.FromAsync を使用してクライアント側のタスクに呼び出しをラップすることにより、WCF 非同期操作の呼び出しを簡素化しようとしています。しかし、ラップされたタスクを Start() すると、デバッガーが ContextSwitchDeadlock を報告するまで、Start() の呼び出しによってクライアントがブロックされます。ただし、サーバー側の操作は正しく呼び出されます。私は何が欠けていますか?
WCF 契約:
[ServiceContract(Namespace = "urn:test/test")]
public interface ITestContract
{
[OperationContract(AsyncPattern=true)]
IAsyncResult BeginGetResult(AsyncCallback callback, object state);
int EndGetResult(IAsyncResult result);
}
クライアントコード:
var task = Task<int>.Factory.FromAsync(
(callback, state) => service.BeginGetResult(callback, state),
(result) => service.EndGetResult(result)
);
task.Start(); // blocks until ContextSwitchDeadlock gets reported
編集:完全を期すために: いいえ、.NET 4.0 (つまり、Windows XP および Server 2003 のサポート) は私のプロジェクトの厳しい要件であるため、.NET 4.5 の async / await パターンは使用できません。
EDIT2:
とにかくへの呼び出しはStart()
必要ありません。本当の問題は、またはBeginGetResult
を呼び出すまでサーバー側で呼び出されないことです。これは、同期呼び出しと同じことになります。Start()
Wait()
Result
私が知ったように、これはタスクとはまったく関係ありません。次のようにすると、同じ結果が得られます。
var asyncResult = service.BeginGetResult(null, null); // BeginGetResult NOT invoked on server side!
asyncResult.AsyncWaitHandle.WaitOne(); // Now BeginGetResult actually gets invoked
EDIT3:
それはすべて私の側の単なる誤解だったことが判明しました。BeginGetResult
クライアント側で呼び出すと、サーバー側で対応するものをすぐにBeginGetResult
呼び出す、つまり、サーバーが実際にリクエストを取得するまでクライアント側でブロックすることを期待してBeginGetResult
いましたが、そうではないようです。どうやらリクエストはバックグラウンド スレッドで送信されるため、クライアント側とサーバー側の への呼び出しの間に遅延が生じる可能性がありますBeginGetResult
。私はこの動作が予想されると思うので、すべて問題ありません:-)。