c#意外的背景员工行为
我在我的主窗体上附加了一个backgroundWorker组件,它运行一个并行任务,为动画gif捕获屏幕。worker函数有一个while循环,它一直运行,直到我在worker上使用c#意外的背景员工行为,c#,winforms,backgroundworker,C#,Winforms,Backgroundworker,我在我的主窗体上附加了一个backgroundWorker组件,它运行一个并行任务,为动画gif捕获屏幕。worker函数有一个while循环,它一直运行,直到我在worker上使用CancelAsync(),此时它退出循环,执行一些其他操作,如保存gif文件等,并将一些结果返回到UI线程 private bool capturing = false; public MainForm() { InitializeComponent(); backgroundWorker.DoW
CancelAsync()
,此时它退出循环,执行一些其他操作,如保存gif文件等,并将一些结果返回到UI线程
private bool capturing = false;
public MainForm()
{
InitializeComponent();
backgroundWorker.DoWork += backgroundWorker_DoWork;
backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
backgroundWorker.WorkerSupportsCancellation = true;
}
private void captureBtn_Click(object sender, EventArgs e)
{
Debug.WriteLine("Button clicked");
if (capturing) { return; }
if (!backgroundWorker.IsBusy)
{
backgroundWorker.RunWorkerAsync();
}
}
private void stopCaptureBtn_Click(object sender, EventArgs e)
{
if (backgroundWorker.IsBusy)
{
backgroundWorker.CancelAsync();
}
}
private void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
capturing = true;
Debug.WriteLine("DoWork running");
while (!backgroundWorker.CancellationPending)
{
Debug.WriteLine("Capturing frame {0}", frames);
//do the capturing to memory stream
}
Debug.WriteLine("DoWork cancelled");
//do some other things like saving the gif etc
e.Result = someResult;
}
private void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
Debug.WriteLine("RunWorkerCompleted running");
capturing = false;
//does something with the e.Result
}
在正常测试期间,我的控制台输出如下:
Button clicked
DoWork running
Capturing frame 0
Capturing frame 1
Capturing frame 2
Capturing frame 3
Capturing frame 4
Capturing frame 5
Cancel button clicked
DoWork cancelled
The thread 0x2e4c has exited with code 0 (0x0).
DoWork running
DoWork cancelled
The thread 0x1010 has exited with code 0 (0x0).
RunWorkerCompleted running
该函数似乎运行了两次,我可以看到两个独立的线程退出,而且我似乎没有从捕获中得到任何结果。如果我在backgroundWorker_DoWork函数中设置了一个断点并在以后继续,那么第一次运行会正常进行捕获。可能发生了什么?线程0x3108已退出,代码为0(0x0),表示没有错误。 在阅读或编写大数据时,你应该将其分成几个部分。否则,你就无法前进。当前while循环在写入内存流时被禁用。 因此,您的backgroundWorker_DoWork方法应如下所示:
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
var worker = (BackgroundWorker)sender;
// this is an example file
string filePath = @"C:\file.gif";
// it determines how many bytes of data will be received from the stream each time.
byte[] buffer = new byte[4096];
int byteCount = 0;
// we are preparing to read stream.
using (FileStream fs = new FileStream(filePath, FileMode.Open, System.IO.FileAccess.Read))
using (MemoryStream ms = new MemoryStream())
{
// read the stream bytes and fill buffer
while ((byteCount = fs.Read(buffer, 0, buffer.Length)) > 0)
{
// if the task was canceled
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
// write buffer to memory stream
ms.Write(buffer, 0, byteCount);
}
}
}
它被调用了两次,因为在InitializeComponent()之后第二次绑定事件。 只需对这些行进行注释,就可以了。 下面是相同的示例,没有运行两次的问题 样本输出 ... ... ... 捕获帧2632 捕获帧2633 捕获帧2634 取消嫁妆 RunWorker完成运行
public partial class Form1 : Form
{
private bool capturing = false;
public Form1()
{
InitializeComponent();
backgroundWorker1.WorkerSupportsCancellation = true;
// Don't need to re-bind
//backgroundWorker1.DoWork += backgroundWorker1_DoWork;
//backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
//backgroundWorker1.WorkerSupportsCancellation = true;
}
private void captureBtn_Click(object sender, EventArgs e)
{
Debug.WriteLine("Button clicked");
if (capturing) { return; }
if (!backgroundWorker1.IsBusy)
{
backgroundWorker1.RunWorkerAsync();
}
}
private void stopCaptureBtn_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy)
{
backgroundWorker1.CancelAsync();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
capturing = true;
Debug.WriteLine("DoWork running");
int frames = 1;
while (!backgroundWorker1.CancellationPending)
{
Debug.WriteLine("Capturing frame {0}", frames);
//do the capturing to memory stream
frames++;
}
Debug.WriteLine("DoWork cancelled");
//do some other things like saving the gif etc
//e.Result = someResult;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Debug.WriteLine("RunWorkerCompleted running");
capturing = false;
//does something with the e.Result
}
在那里声明一个额外的变量bool。在
backgroundWorker\u DoWork
中将其设置为true,然后在backgroundWorker\u RunWorkerCompleted
中将其设置为false。然后在启动工作程序之前,在captureBtn_单击例行程序中检查此项。这会有帮助吗,我有一种感觉,快速双击或者发生了什么事情,或者其他一些可能被你的帖子遗漏的事情代码>。行为完全相同。我还检查了captureBtn\u Click
似乎只运行了一次。我还注意到backgroundWorker\u RunWorkerCompleted
只在底部运行。正如RunWorkerCompleted的名称所示:它在完成工作时运行。你能告诉我们那个的密码吗?我在你的问题中没有看到。我用新的调试帖子和缺少的函数更新了我的代码。这确实是问题所在。在表单中创建工人时,我没有意识到嫁妆已经绑定。