要求:
我更喜欢在BackgroundWorker中“同步”执行此操作,但这会打破SL异步思维。
我的代码目前将结果从OpenFileDialog传递给BackgroundWorker,后者将文件读入强类型对象列表(客户端验证)。我创建一个WebClient并多次调用DownloadStringAsync,因为我循环遍历这些行。通常,后台工作程序在WebClient完成之前很久就完成并运行已完成的事件方法。 UI线程可以根据需要以异步方式运行,但我需要等待完成后台工作线程,直到它实际完成数据获取,或者有一些额外的事件处理程序在所有(数百)行已经过验证时有效。
想要处理X总事件的最后一次完成事件时,最佳做法是什么?在这里使用自动重置事件有什么用呢?
答案 0 :(得分:1)
你不需要去那个后台线程,也不需要在这里使用AutoResetEvent
。读取文件后,计算行数(=您要发送的请求数)并将其存储在实例变量中;然后触发所有WebRequest.DownloadAsync
(或其他WebClient
异步调用以下载数据)。在异步方法的每个回调中,您Interlock.Decrement
实例变量,当它达到0时,您知道您拥有所有结果,并且您可以将摘要显示给客户端。
答案 1 :(得分:1)
您可以选择随机响应序列(但并行执行) 或顺序响应,但顺序模式。 有不同的缺点和优点。
using System;
using System.Net;
using System.Reactive.Linq;//Rx libriary
using System.Threading;
using System.Windows;
using System.Windows.Controls;
public partial class MainPage : UserControl
{
private int count = 0;
private int error = 0;
public MainPage()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem(StartParallel);
//ThreadPool.QueueUserWorkItem(StartSequential);
}
private void Update(Exception exception)
{
if (exception == null)
Interlocked.Increment(ref count);
else
Interlocked.Increment(ref error);
if ((count%100) == 0)
{
int count1 = count;
Dispatcher.BeginInvoke(() => { textBox.Text = count1.ToString(); });
}
}
private void StartSequential(object o)
{
//single instance of WebClient
WebClient wc = new WebClient();
var observer = Observable.FromEventPattern<DownloadStringCompletedEventArgs>(wc, "DownloadStringCompleted")
.Select(newResult => new {newResult.EventArgs.Error, newResult.EventArgs.Result});
wc.DownloadStringAsync(new Uri("http://localhost:7123/SilverlightApplication2TestPage.aspx"));
int i = 0;
foreach (var nextValue in observer.Next())
{
if (i == 10000) break;
wc.DownloadStringAsync(new Uri("http://localhost:7123/SilverlightApplication2TestPage.aspx"));
Update(nextValue.Error);
}
}
private void StartParallel(object o)
{
for (int i = 0; i < 10000; i++)
{
//multiple instance of WebClient
WebClient t = new WebClient();
t.DownloadStringCompleted +=
(x, nextValue) => Update(nextValue.Error);//order of result sequence is not guaranteed
t.DownloadStringAsync(new Uri("http://localhost:7123/SilverlightApplication2TestPage.aspx"));
}
}
}