我想编写一个小的Silverlight应用程序,其中我有三个DataGrids。每个Datagrid使用异步方法从gets服务获取数据。现在,我希望第一个数据网格从webservice获取数据,然后使用第一个datagrid中选定行的参数从webservice获取第二个datagrid,并使用前两个datagrids中的参数获取第三个datagrid。第一个datagrid通过注册事件处理程序获取MainPage方法中的数据,然后使用异步方法。
现在我的问题是,我在SelectionChanged (事件处理)方法中对其他数据网格使用了异步方法,我猜这样的概念是错误的,因为在数据网格2中选择了一些东西并返回到数据网格1之后,所有的数据网格都消失了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ServiceModel;
using Rebat.SymptomeService;
namespace Rebat
{
public partial class MainPage : UserControl
{
ServiceClient client = new ServiceClient();
public MainPage()
{
InitializeComponent();
ServiceClient client = new ServiceClient();
client.SymptomeListCompleted += new EventHandler<SymptomeListCompletedEventArgs>(client_SymptomeListCompleted);
client.SymptomeListAsync();
}
void client_SymptomeListCompleted(object sender, SymptomeListCompletedEventArgs e)
{
CustomerGrid.ItemsSource = e.Result;
}
void client_CustomerListCompleted(object sender, CustomerListCompletedEventArgs e)
{
CustomerGrid2.ItemsSource = e.Result;
}
void client_SalzListCompleted(object sender, SalzListCompletedEventArgs e)
{
SalzGrid.ItemsSource = e.Result;
}
private void CustomerGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Symptome sympt = CustomerGrid.SelectedItem as Symptome;
client.CustomerListCompleted += new EventHandler<CustomerListCompletedEventArgs>(client_CustomerListCompleted);
client.CustomerListAsync(sympt.sId.ToString());
}
private void CustomerGrid2_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Symptome2 sympt2 = CustomerGrid2.SelectedItem as Symptome2;
client.SalzListCompleted += new EventHandler<SalzListCompletedEventArgs>(client_SalzListCompleted);
//this is the PROBLEM:
client.SalzListAsync(sympt2.sy1.ToString(), sympt2.sy2.ToString());
}
}
}我必须更改什么,或者我必须如何使用异步方法?您可以在事件处理方法中使用异步方法吗?这是否适用于消费Does服务的使用?
发布于 2012-11-15 01:41:11
假设你可以使用.NET 4.5的异步功能,如果你让你的服务代理适应基于任务的异步模式,那么做这类调用就会简单得多。您可以在事件处理程序中使用async方法,您只需将其设为async即可充分受益于新的async/await关键字。
要调整代理,首先要声明一个helper静态类:
public static partial class TAPExtensions
{
public static void HandleCompletion<T>(TaskCompletionSource<T> tcs, AsyncCompletedEventArgs args, Func<T> getResult, Action unregisterHandler = null)
{
// Transfers the results from the AsyncCompletedEventArgs and getResult() to the
// TaskCompletionSource, but only AsyncCompletedEventArg's UserState matches the TCS
// (this check is important if the same WebClient is used for multiple, asynchronous
// operations concurrently). Also unregisters the handler to avoid a leak.
if (args.UserState == tcs)
{
if (args.Cancelled) tcs.TrySetCanceled();
else if (args.Error != null) tcs.TrySetException(args.Error);
else tcs.TrySetResult(getResult());
if (unregisterHandler != null) unregisterHandler();
}
}
}现在,创建另一个帮助器类来扩展您的代理。为每个操作创建一个适配器方法:
public static class ServiceClientEx
{
public static async Task<IEnumerable<ReturnType>> SalzListTask(this ServiceClient proxy, string arg1, string arg2)
{
var tcs = new TaskCompletionSource<IEnumerable<ReturnType>>();
EventHandler<SalzListCompletedEventArgs> handler = (s, args) => TAPExtensions.HandleCompletion(tcs, args, () => args.Result);
proxy.SalzListCompleted += handler;
try
{
proxy.SalzListAsync(arg1, arg2, tcs);
return await tcs.Task;
}
finally { proxy.SalzListCompleted -= handler; }
}
}现在,您可以在代码中使用扩展方法(假设为ServiceClientEx类的名称空间添加了一个"using“指令)。结果会是这样的:
public partial class MainPage : UserControl
{
ServiceClient client = new ServiceClient();
public MainPage()
{
InitializeComponent();
ServiceClient client = new ServiceClient();
}
private async void CustomerGrid2_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Symptome2 sympt2 = CustomerGrid2.SelectedItem as Symptome2;
alzGrid.ItemsSource = await client.SalzListTask(sympt2.sy1.ToString(), sympt2.sy2.ToString());
}
}注意在eventhandler声明中使用了"async“关键字。它将异步行为传播到方法:一旦选择更改,处理程序将正常执行,直到它到达第一个等待,此时它将返回到原始调用方(控件的调度程序)。当调用结束时,continuation (将itemssource设置为操作结果)将在UIThread中执行。
您甚至可以包装调用以检查异常,如下所示:
private async void CustomerGrid2_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try{
Symptome2 sympt2 = CustomerGrid2.SelectedItem as Symptome2;
alzGrid.ItemsSource = await client.SalzListTask(sympt2.sy1.ToString(), sympt2.sy2.ToString());
}catch(MyException ex){
MessageBox.Show(ex.ToString());
}
}一些建议:
https://stackoverflow.com/questions/13200145
复制相似问题