基本的に質問が述べているように、サービスを非同期にすると、サービスが相互運用できなくなるということですか?
3 に答える
クライアントに関する限り、サービスの同期バージョンと非同期バージョンは同じです (以下の例を参照)。したがって、同期/非同期の決定は相互運用性に影響しません。
public class StackOverflow_6231864_751090
{
[ServiceContract(Name = "ITest")]
public interface ITest
{
[OperationContract]
string Echo(string text);
[OperationContract]
int Add(int x, int y);
}
[ServiceContract(Name = "ITest")]
public interface ITestAsync
{
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginEcho(string text, AsyncCallback callback, object state);
string EndEcho(IAsyncResult ar);
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginAdd(int x, int y, AsyncCallback callback, object state);
int EndAdd(IAsyncResult ar);
}
public class Service : ITest
{
public string Echo(string text) { return text; }
public int Add(int x, int y) { return x + y; }
}
public class ServiceAsync : ITestAsync
{
string Echo(string text) { return text; }
int Add(int x, int y) { return x + y; }
public IAsyncResult BeginEcho(string text, AsyncCallback callback, object state)
{
Func<string, string> func = Echo;
return func.BeginInvoke(text, callback, state);
}
public string EndEcho(IAsyncResult ar)
{
Func<string, string> func = (Func<string, string>)((System.Runtime.Remoting.Messaging.AsyncResult)ar).AsyncDelegate;
return func.EndInvoke(ar);
}
public IAsyncResult BeginAdd(int x, int y, AsyncCallback callback, object state)
{
Func<int, int, int> func = Add;
return func.BeginInvoke(x, y, callback, state);
}
public int EndAdd(IAsyncResult ar)
{
Func<int, int, int> func = (Func<int, int, int>)((System.Runtime.Remoting.Messaging.AsyncResult)ar).AsyncDelegate;
return func.EndInvoke(ar);
}
}
public static void Test()
{
foreach (bool useAsync in new bool[] { false, true })
{
Type contractType = useAsync ? typeof(ITestAsync) : typeof(ITest);
Type serviceType = useAsync ? typeof(ServiceAsync) : typeof(Service);
Console.WriteLine("Using {0} service implementation", useAsync ? "Asynchronous" : "Synchronous");
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(serviceType, new Uri(baseAddress));
host.AddServiceEndpoint(contractType, new BasicHttpBinding(), "");
host.Open();
Console.WriteLine("Host opened");
Console.WriteLine("Using the same client for both services...");
ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
ITest proxy = factory.CreateChannel();
Console.WriteLine(proxy.Echo("Hello"));
Console.WriteLine(proxy.Add(3, 4));
((IClientChannel)proxy).Close();
factory.Close();
host.Close();
Console.WriteLine("Done");
Console.WriteLine();
}
}
}
あなたのサービスは「特別な」ことをする必要はありません...それでも同じように動作します。一方、クライアントは非同期パターンを使用してサービスを利用する必要があります。これを行う最も簡単な方法は、「サービス参照の追加...」を使用することです。「Generate Asynchronous Operations」という小さなボックスをチェックするだけで、サービスへの非同期呼び出しを行うことができます...
ここに良いリソースがあります:方法: WCF サービス操作を非同期的に呼び出す
否定的なコメントにもかかわらず、最後の例はうまくまとめられています。<service-name>Completedイベントをサブスクライブしてから、Async 呼び出しを行うだけです。呼び出しが行われ、UI スレッドが解放され、呼び出しが完了するとすぐにイベントが発生します! 新たに発見された力に注意してください!
public class Foo
{
private BarServiceClient client;
public Foo()
{
client = new BarServiceClient();
client.DoWorkCompleted += Client_DoWorkCompleted;
}
private void Client_DoWorkCompleted(object sender, DoWorkCompletedEventArgs e)
{
//e.Result contains your result.
}
public void DoBar()
{
client.DoWorkAsync(); //Called asynchronously, UI thread is free! :)
}
}
「サービスを非同期にする」とは、を使用することを意味する場合AsyncPattern
、私の理解では、これはクライアントにはまったく影響せず、WCF ランタイムがサーバー上で操作を呼び出す方法にのみ影響します。クライアント (つまり、WCF クライアント) は、これまでどおり、非同期呼び出しを使用するかどうかを独自に選択します。
クライアント アプリケーションでの呼び出し方法に関係なく、非同期で実行されるコントラクト操作 X を定義するには...
と:
この場合、非同期操作は、同期操作と同じ形式でメタデータに公開されます。つまり、要求メッセージと相関する応答メッセージを含む単一の操作として公開されます。クライアント プログラミング モデルには選択肢があります。サービスが呼び出されたときに要求と応答のメッセージ交換が行われる限り、このパターンを同期操作または非同期操作として表すことができます。