我同意,应该有一些比你目前的方法更容易。但是,除非我们可以使用T4模板来生成代理类,否则,除非你想推出自己的(不推荐IMO,YMMV),否则按照你已经尝试过的方式来看,你认为最好的方法就是拍摄。
我目前正在使用这两种方法的混合。我已经将所有WCF调用包装在一系列数据访问类中,这些类将MS提供的不太有用的事件驱动模型转换为更简单的回调方法。在这些数据访问类中,我还使用一个静态的PreProcessCall()方法来封装每个调用,该方法处理增加未完成的调用计数器并将调用编组到后台线程;我用静态的PostProcessCall()方法封装了每个返回调用,该方法递减未完成的调用计数器并将回调编组到UI线程中。
public static void PreProcessCall(Action action)
{
Logger.LogDebugMessage("Pre-processing call for {0}", (new StackTrace()).GetFrame(1).GetMethod().Name);
Interlocked.Increment(ref pendingCalls);
ThreadPool.QueueUserWorkItem(o =>
{
try
{
action();
}
catch (System.Exception ex)
{
DataPublisher.GetPublisher().RaiseDataProcessExceptionOccurred(ex, ex.Message);
UpdatePendingCalls();
}
});
}
private static void UpdatePendingCalls()
{
Interlocked.Decrement(ref pendingCalls);
Debug.Assert(pendingCalls >= 0, "The number of pending calls should never go below zero.");
if (pendingCalls <= 0)
{
lock (pendingCallNotifications)
{
while (pendingCallNotifications.Count > 0)
{
Action callback = pendingCallNotifications.Dequeue();
Globals.Dispatcher.BeginInvoke(callback);
}
}
}
}
public static void PostProcessCall(Action action)
{
Logger.LogDebugMessage("Post-processing call for {0}", (new StackTrace()).GetFrame(1).GetMethod().Name);
UpdatePendingCalls();
Globals.Dispatcher.BeginInvoke(() =>
{
try
{
action();
}
catch (System.Exception ex)
{
DataPublisher.GetPublisher().RaiseDataProcessExceptionOccurred(ex, ex.Message);
}
});
}
因此,一个典型的调用看起来是这样的:
public void SendMessage(string message, OperationCallback callback)
{
DataConnectionManager.PreProcessCall(() =>
{
Logger.LogDebugMessage("SendChatMessage");
notificationClient.SendChatMessageAsync(roomViewModel.SessionId, message, callback);
});
}
void RoomService_SendChatMessageCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
OperationCallback callback = (OperationCallback)e.UserState;
DataConnectionManager.PostProcessCall(() =>
{
if (callback != null)
{
callback(e.Error);
}
Logger.LogDebugMessage("SendChatMessageCompleted.");
});
}
就像我说的,基本上你已经尝试过。
不是开箱即用的,但是当您调用BeginXXXX并将其设置回来时,设置一个小布尔标志会相当容易,那么输入EndXXX回调,不是吗? – 2010-01-19 22:14:17