这是解决方案的简化计划: 由于某些原因,我需要通过另一个背景工作者运行的后台工作程序运行Windows窗体,当新的窗体加载时,旧的后台工作者必须暂停。我写这样的代码:
创建一个名为:temp
的类public class temp
{
static public BackgroundWorker backgroundWorker1 = new BackgroundWorker() { WorkerSupportsCancellation = true };
static public EventWaitHandle ew = new EventWaitHandle(false, EventResetMode.ManualReset);
static public BackgroundWorker back = new BackgroundWorker() { WorkerSupportsCancellation = true };
}
form1的代码是:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
temp.backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
temp.back.DoWork += new DoWorkEventHandler(back_DoWork);
}
void back_DoWork(object sender, DoWorkEventArgs e)
{
Form2 f = new Form2();
f.Show();
}
private void button1_Click(object sender, EventArgs e)
{
temp.backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
temp.back.RunWorkerAsync();
if (temp.backgroundWorker1.CancellationPending)
temp.ew.WaitOne();
}
}
}
并且form2的代码在这里:
namespace WindowsFormsApplication1
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
temp.backgroundWorker1.CancelAsync();
temp.ew.Reset();
}
}
}
通过单击form1中的button1运行temp.backgroundworker1然后在temp.backgroundworker1的DoWork中运行temp.back然后运行FORM2 LOADS但FORM2挂起并且成为无用的,你不能再使用它了。 我哪里错了? 我要执行的整个计划是: 我们有一个For循环来处理DataGridView的每一行。 每次在某一点上,另一个窗口打开 并且它会停止循环,直到用户插入信息然后单击“确定”按钮,windowsform关闭并且循环继续工作。我不知道该怎么做.......
即使我不像下面的代码那样取消form2load中temp.backgroundworker的工作,Form2也没用了
private void Form2_Load(object sender, EventArgs e)
{
}
答案 0 :(得分:0)
不要在工作线程中使用任何UI操作(DoWork
方法)。也许这就是为什么你设置CheckForIllegalCrossThreadCalls
属性,但你的应用程序无法正常工作只是在附加调试器时抑制错误。
请参阅我的回答here以正确使用BackgroundWorker
(关于取消,但您可以在UI和工作线程中查看操作)。
在这种特殊情况下,您可以使用类似的volatile bool
来签署可以显示表单的UI线程。或者,如果要在线程之间发送不同的消息,请使用ConcurrentQueue<T>
来编写和读取消息:
public partial class Form1 : Form
{
private enum Message
{
ShowForm2,
SuspendWork,
ResumeWork,
FinishWorker1
// ... and whatever you want
}
private Timer timer;
private ConcurrentQueue<Message> messagesToUI = new ConcurrentQueue<Message>();
private ConcurrentQueue<Message> messagesToWorker = new ConcurrentQueue<Message>();
public Form1()
{
InitializeComponent();
timer = new Timer(this);
timer.Interval = 10;
timer.Tick += PollUIMessages;
timer.Enabled = true;
}
void PollUIMessages(object sender, EventArgs e)
{
// do we have a new message?
Message message;
if (messagesToUI.TryDequeue(out message))
{
switch (message)
{
case Message.ShowForm2:
Form2 f = new Form2();
f.Show();
// todo: in Form2.Close add a Resume message to the messagesToWorker
break;
// ... process other messages
}
}
}
void back_DoWork(object sender, DoWorkEventArgs e)
{
// Here you are in the worker thread. You can send a message to the
// UI thread like this:
messagesToUI.Enqueue(Message.ShowForm2);
bool isWorking = true;
// and here you can poll the messages to the worker thread
while (true)
{
Message message;
if (!messagesToWorker.TryDequeue(out message))
{
// no message: idle or work
if (isWorking)
DoSomeWork(); // do whatever you want
else
Thread.CurrentThread.Sleep(10);
continue;
}
switch (message)
{
case Message.FinishWorker1:
// finishing the worker: jumping out
return;
case Message.SuspendWork:
isWorking = false;
break;
case Message.ResumeWork:
isWorking = true;
break;
}
}
}