使用Task简化Silverlight调用Wcf(续)
上一篇 使用Task简化Silverlight调用Wcf 介绍了Silverlight下使用Task的一些方法,这篇继续改进一下。
改进生成工具的生成的方法上次生成的代码如下,这些TaskAsync只是简单的包装一下Wcf的begin和end方法:
public Task DoWorkTaskAsync()
{
return Task.Factory.FromAsync( this .Channel.BeginDoWork, this .Channel.EndDoWork, null );
}
public Task<DateTime> GetSerivceTimeTaskAsync()
{
return Task<DateTime>.Factory.FromAsync( this .Channel.BeginGetSerivceTime, this .Channel.EndGetSerivceTime, null );
}
调用时需要手动去Wait():
private void OnGetTimeClick( object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem(s =>
{
var task = _systemServiceClient.GetSerivceTimeTaskAsync();
task.Wait();
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(task.Result.ToString());
});
});
}
这次生成的方法连task1.Wait(); 也包含了,多生成一个方法来Wait:
public Task DoWorkTaskAsync()
{
return Task.Factory.FromAsync( this .Channel.BeginDoWork, this .Channel.EndDoWork, null );
}
public void DoWork()
{
var task = DoWorkTaskAsync();
task.Wait();
}
public Task<DateTime> GetSerivceTimeTaskAsync()
{
return Task<DateTime>.Factory.FromAsync( this .Channel.BeginGetSerivceTime, this .Channel.EndGetSerivceTime, null );
}
public DateTime GetSerivceTime()
{
var task = GetSerivceTimeTaskAsync();
task.Wait();
return task.Result;
}
这样调用包含Wait的方法就直接返回结果了,而不是返回Task,再去Wait():
private void OnGetTimeClick( object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem(s =>
{
var time = _systemServiceClient.GetSerivceTime();
Dispatcher.BeginInvoke(() => MessageBox.Show(time.ToString()));
});
}
UI同步技巧调用Wcf和UI交互需要顺序进行是最平常的需求,这时需要与UI交互也有“同步”的能力。例如:
ThreadPool.QueueUserWorkItem(s =>
{
//调用Wcf
var num = _systemServiceClient.GetNum(5);
//UI对话框询问是否继续
var result = childWin.ShowSync();
if (result == false )
return ;
var time = _systemServiceClient.GetSerivceTime();
.......
});
如果是UI线程的话是不可以这样阻塞的,然而这里是后台线程,阻塞也是没所谓的,所以可以使用下面的方法来阻塞线程,来模拟同步:
public partial class TestChildWindow : ChildWindow
{
private readonly ManualResetEvent _manualResetEvent;
public TestChildWindow()
{
InitializeComponent();
_manualResetEvent = new ManualResetEvent( false );
Closed += (_, __) => _manualResetEvent.Set();
}
public bool ? ShowSync()
{
if (Dispatcher.CheckAccess())
throw new InvalidOperationException( "ShowSync只能使用后台线程调用!" );
Dispatcher.BeginInvoke(Show);
_manualResetEvent.Reset();
_manualResetEvent.WaitOne();
return DialogResult;
}
.........
}
这里使用 ManualResetEvent 类来等待,打开窗体后马上阻塞,直到子窗体Closed时通知结束,实现”同步“。
这里注意ShowSync的Dispatcher.CheckAccess()判断,明确只能再后台线程里调用。
示例:
private void OnMultiTaskClick( object sender, RoutedEventArgs e)
{
var childWin = new TestChildWindow();
ThreadPool.QueueUserWorkItem(s =>
{
const string format = "Num:{1},{0}{2},{0}Time:{3},{0}UserCount:{4},{0}ChildWinResult:{5}" ;
var num = _systemServiceClient.GetNum(5);
var str = _systemServiceClient.SayHiTo(num.ToString());
//这里是“同步”的
var result = childWin.ShowSync();
var time = _systemServiceClient.GetSerivceTime();
var all = _userServiceClient.GetAll();
var msg = string .Format(format, Environment.NewLine, num, str, time, all.Count, result);
Dispatcher.BeginInvoke(() => MessageBox.Show(msg));
});
}
工具和测试源码 http://www.cnblogs.com/lemontea/archive/2013/02/03/2890586.html
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于使用Task简化Silverlight调用Wcf(续)的详细内容...