我注意到 BackgroundWorkers 的一些奇怪行为以及它们正在触发的事件,其中事件似乎在一个线程中排队,而实际上并未使用 CPU。
基本上系统的设计是,基于用户交互,创建一个线程来发送 Web 请求以获取一些数据。根据结果,它可能会触发许多其他异步请求,对每个请求使用 BackgroundWorkers。我这样做是因为管理请求的代码使用锁来确保一次只发送一个请求(以避免向服务器发送多个同时请求的垃圾邮件,可能导致服务器忽略/阻止它们)。可能有更好的设计,我很想听听(我对 C#/Windows 窗体编程比较陌生,可以使用这些建议)。但是,无论设计更改如何,我都有兴趣了解导致我所看到的行为的原因。
我编写了一个相对简单的测试应用程序来演示这个问题。它基本上只是一个带有按钮和文本框的表单来显示结果(您可能可以不使用表单并在控制台上显示结果,但我这样做是为了复制我的实际应用程序所做的事情)。这是代码:
delegate void AddToLogCallback(string str);
private void AddToLog(string str)
{
if(textBox1.InvokeRequired)
{
AddToLogCallback callback = new AddToLogCallback(AddToLog);
Invoke(callback, new object[] { str });
}
else
{
textBox1.Text += DateTime.Now.ToString() + " " + str + System.Environment.NewLine;
textBox1.Select(textBox1.Text.Length, 0);
textBox1.ScrollToCaret();
}
}
private void Progress(object sender, ProgressChangedEventArgs args)
{
AddToLog(args.UserState.ToString());
}
private void Completed(object sender, RunWorkerCompletedEventArgs args)
{
AddToLog(args.Result.ToString());
}
private void DoWork(object sender, DoWorkEventArgs args)
{
BackgroundWorker worker = sender as BackgroundWorker;
lock (typeof(Form1)) // Ensure only a single request at a time
{
worker.ReportProgress(0, "Start");
Thread.Sleep(2000); // Simulate waiting on the request
worker.ReportProgress(50, "Middle");
Thread.Sleep(2000); // Simulate handling the response from the request
worker.ReportProgress(100, "End");
args.Result = args.Argument;
}
}
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(RunMe);
thread.Start();
}
private void RunMe()
{
for(int i=0; i < 20; i++)
{
AddToLog("Starting " + i.ToString());
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += DoWork;
worker.RunWorkerCompleted += Completed;
worker.ProgressChanged += Progress;
worker.RunWorkerAsync(i);
}
}
这是我回来的结果:
30/07/2009 2:43:22 PM Starting 0
30/07/2009 2:43:22 PM Starting 1
<snip>
30/07/2009 2:43:22 PM Starting 18
30/07/2009 2:43:22 PM Starting 19
30/07/2009 2:43:23 PM Start
30/07/2009 2:43:36 PM Middle
30/07/2009 2:43:36 PM End
30/07/2009 2:43:36 PM 0
30/07/2009 2:43:36 PM Start
30/07/2009 2:43:36 PM Middle
30/07/2009 2:43:36 PM End
30/07/2009 2:43:36 PM 1
30/07/2009 2:43:36 PM Start
30/07/2009 2:43:36 PM Middle
30/07/2009 2:43:36 PM End
30/07/2009 2:43:36 PM 8
30/07/2009 2:43:36 PM Start
30/07/2009 2:43:36 PM Middle
30/07/2009 2:43:38 PM 13
30/07/2009 2:43:38 PM End
30/07/2009 2:43:38 PM Start
30/07/2009 2:43:40 PM Middle
30/07/2009 2:43:42 PM 18
30/07/2009 2:43:42 PM Start
30/07/2009 2:43:42 PM End
30/07/2009 2:43:44 PM Middle
30/07/2009 2:43:46 PM End
30/07/2009 2:43:46 PM 2
30/07/2009 2:43:46 PM Start
30/07/2009 2:43:48 PM Middle
如您所见,在显示第一条“开始”消息后有 13 秒的延迟,之后它会处理大约 15 条消息(尽管大多数消息被触发之间有 2 秒的延迟)。
有谁知道发生了什么?