在Silverlight 4中,从UI线程发出的所有WCF调用必须是异步的。这可以。 WCF客户端代码公开方法和事件,如
void GetDataAsync(SomeArgument a);
event EventHandler<GetDataCompletedEventArgs> GetDataCompleted;
是否可以将其包装或配置WCF / Silverlight以生成以下内容?
void GetDataAsync(SomeArgument a, EventHandler<GetDataCompletedEventArgs>);
在我的项目中,我创建了一个负责所有方法调用的类,可以访问更高层(如视图模型)。它公开了如下方法:
void GetData(SomeArgument a, Action<SomeResult> callback);
现在serviceClient
可重复使用,因此我需要在呼叫结束后取消订阅* Completed事件。到目前为止,我最好的方法是:
EventHandler<T> MakeHandler<T>(Action<T> callback) where T : AsyncCompletedEventArgs
{
return (sender, eventArgs) =>
{
callback(eventArgs); // perform some operations in view model
((Action)eventArgs.UserState)(); // this is to unsubscribe from event
};
}
void GetData(SomeArgument a, Action<SomeResult> callback)
{
var handler = MakeHandler<GetDataCompletedEventArgs>((s, ea) => callback(ea.Result));
serviceClient.GetDataCompleted += handler
serviceClient.GetDataAsync(a, new Action(() => serviceClient.GetDataCompleted -= handler));
}
我真的想避免为每个使用过的WCF方法重新键入整个GetData()连接,并执行以下操作:
void GetData(SomeArgument a, Action<SomeResult> callback)
{
serviceClient.GetDataAsync(a, callback);
}
答案 0 :(得分:3)
您可以使用ServiceClient的Service接口访问WCF服务的开始/结束“.NET异步模式”。例如,如果您有一个名为“Service1”的WCF服务,您的Silverlight项目将包含一个“Service1Client”类(使用Async / Event模式来公开操作),但它还显式实现了一个名为“Service1”的接口,它使用了Begin /每个操作的结束对。使用: -
Service1 service = new Service1Client();
现在可以访问Begin / End对,事情变得容易一些。您可以使用以下通用函数来创建调用异步模式的基本管道:
public static Action<Action<T>, Action<Exception>> AsyncExecute<T>(Action<AsyncCallback> begin, Func<IAsyncResult, T> end)
{
return (success, fail) =>
{
AsyncCallback cb = (ar) =>
{
try
{
success(end(ar));
}
catch (Exception err)
{
fail(err);
}
};
begin(cb);
};
}
您可以使用特定功能使用它:
void GetData(SomeArgument a, Action<SomeResult> success)
{
var fn = AsyncExecute<SomeResult>(cb => service.BeginGetData(a, cb, null), service.EndGetData);
fn(success, GeneralFail);
}
public static void GeneralFail(Exception err)
{
// General reporting of fail
}