使用 BeginInvoke 进行 UI 更新挂起直至线程完成?

发布于 2024-11-04 15:04:14 字数 3170 浏览 5 评论 0原文

我有 1 个类 (acBL),它处理 2 个线程 (fpDoWork)。 fpDoWork 中完成的任何工作都会触发一个事件返回 acBL 类。在我的表单上,我声明了 acBL 类并在 acBL 上关联事件处理程序 - 这样每当调用事件时,它“应该”通过更改来更新 UI。

没有发生的是,当每个fpDoWork线程启动时,它执行操作,调用ProcessingEvent并进入frmMain.handlerProcessing1事件。它到达了调用 this.BeginInvoke(new Processing2Event (handlerProcessing2), status) 的地方,然后它只是挂起并等待,直到线程完成其工作,然后再继续更新 UI。我尝试了 this.Invoke,但该方法似乎挂起。有什么想法吗?

frmMain 内的代码

代码中的较早部分:

this.acBL.Processing1Event += new acBL.Processing1(handlerProcessing1);
this.acBL.Processing2Event += new acBL.Processing2(handlerProcessing2);

处理程序:

private void handlerProcessing1(string status) {
  if (InvokeRequired) {
    this.BeginInvoke(new MethodInvoker(this.Refresh));
    this.BeginInvoke(new Processing1Event (handlerProcessing1), status);

  }
  else {
    Console.WriteLine("UPDATING 1: "+status);
    lblForProcessing1.Text = status;
    this.Refresh();
    return;
  }
}


private void handlerProcessing2(string status) {
  if (InvokeRequired) {
    this.BeginInvoke(new MethodInvoker(this.Refresh));
    this.BeginInvoke(new Processing2Event (handlerProcessing2), status);

  }
  else {
    Console.WriteLine("UPDATING 2: "+status);
    lblForProcessing2.Text = status;
    this.Refresh();
    return;
  }
}

acBL 内的代码

在 main 方法中:

bool thread1Complete = false;
fpDoWork fpDoWork1 = new fpDoWork();
fpDoWork1.GUIForm = frmMain;
fpDoWork1.ProcessingEvent += new fpDoWork.Processing(handlerProcessing1Event);
fpDoWork1.ThreadCompleteEvent += new fpDoWork.ThreadComplete(thread1Complete);
Thread fpDoWork1Thread= new Thread(new ThreadStart(fpDoWork1.StartWork));

bool thread2Complete = false;
fpDoWork fpDoWork2 = new fpDoWork();
fpDoWork2.GUIForm = frmMain;
fpDoWork2.ProcessingEvent += new fpDoWork.Processing(handlerProcessing2Event);
fpDoWork2.ThreadCompleteEvent += new fpDoWork.ThreadComplete(thread2Complete);
Thread fpDoWork2Thread= new Thread(new ThreadStart(fpDoWork2.StartWork));

Console.WriteLine("Work for 1 Thread started...");
fpDoWork1Thread.Start();
Console.WriteLine("Work for 2 Thread started...");
fpDoWork2Thread.Start();

while (!thread1Complete && !thread2Complete ) {
  if (!thread1Complete && !thread2Complete ) {
    Console.WriteLine("Waiting for both copying threads...");
  }
  else if (!thread1Complete && thread2Complete ) {
    Console.WriteLine("Waiting for thread 1...");
  }
  else if (thread1Complete && !thread2Complete ) {
    Console.WriteLine("Waiting for thread 2...");
  }
  Thread.Sleep(1000);
}
Console.WriteLine("All done");

代码中的其他位置:

public delegate void ProcessingFor1 (string filename);
public delegate void ProcessingFor2 (string filename);
public event ProcessingFor1 ProcessingEventFor1;
public event ProcessingFor2 ProcessingEventFor2;


private void handlerProcessing1Event(string filename) {
  Console.WriteLine("Processing 1: " + filename);
  ProcessingEventFor1(filename);
}

private void handlerProcessing1Event(string filename) {
  Console.WriteLine("Processing 2: " + filename);
  ProcessingEventFor2(filename);
}

I have 1 class (acBL) which handles 2 threads (fpDoWork). Any work that is done in fpDoWork will trigger an event back to the acBL class. On my form I declare the acBL class and associate Event handlers on acBL - this way whenever the event is called, it 'should' update the UI with changes.

What is not happening is, when each fpDoWork thread is started, it performs the operations, the ProcessingEvent is called and does go into the frmMain.handlerProcessing1 event. It gets to the point where this.BeginInvoke(new Processing2Event (handlerProcessing2), status) is called, then it just hangs and waits until the thread has finished its work before continuing to update the UI. I tried this.Invoke, but that method just seems to hang. Any ideas?

Code inside frmMain

Earlier in the code:

this.acBL.Processing1Event += new acBL.Processing1(handlerProcessing1);
this.acBL.Processing2Event += new acBL.Processing2(handlerProcessing2);

Handlers:

private void handlerProcessing1(string status) {
  if (InvokeRequired) {
    this.BeginInvoke(new MethodInvoker(this.Refresh));
    this.BeginInvoke(new Processing1Event (handlerProcessing1), status);

  }
  else {
    Console.WriteLine("UPDATING 1: "+status);
    lblForProcessing1.Text = status;
    this.Refresh();
    return;
  }
}


private void handlerProcessing2(string status) {
  if (InvokeRequired) {
    this.BeginInvoke(new MethodInvoker(this.Refresh));
    this.BeginInvoke(new Processing2Event (handlerProcessing2), status);

  }
  else {
    Console.WriteLine("UPDATING 2: "+status);
    lblForProcessing2.Text = status;
    this.Refresh();
    return;
  }
}

Code inside acBL

In a main method:

bool thread1Complete = false;
fpDoWork fpDoWork1 = new fpDoWork();
fpDoWork1.GUIForm = frmMain;
fpDoWork1.ProcessingEvent += new fpDoWork.Processing(handlerProcessing1Event);
fpDoWork1.ThreadCompleteEvent += new fpDoWork.ThreadComplete(thread1Complete);
Thread fpDoWork1Thread= new Thread(new ThreadStart(fpDoWork1.StartWork));

bool thread2Complete = false;
fpDoWork fpDoWork2 = new fpDoWork();
fpDoWork2.GUIForm = frmMain;
fpDoWork2.ProcessingEvent += new fpDoWork.Processing(handlerProcessing2Event);
fpDoWork2.ThreadCompleteEvent += new fpDoWork.ThreadComplete(thread2Complete);
Thread fpDoWork2Thread= new Thread(new ThreadStart(fpDoWork2.StartWork));

Console.WriteLine("Work for 1 Thread started...");
fpDoWork1Thread.Start();
Console.WriteLine("Work for 2 Thread started...");
fpDoWork2Thread.Start();

while (!thread1Complete && !thread2Complete ) {
  if (!thread1Complete && !thread2Complete ) {
    Console.WriteLine("Waiting for both copying threads...");
  }
  else if (!thread1Complete && thread2Complete ) {
    Console.WriteLine("Waiting for thread 1...");
  }
  else if (thread1Complete && !thread2Complete ) {
    Console.WriteLine("Waiting for thread 2...");
  }
  Thread.Sleep(1000);
}
Console.WriteLine("All done");

Else where in the code:

public delegate void ProcessingFor1 (string filename);
public delegate void ProcessingFor2 (string filename);
public event ProcessingFor1 ProcessingEventFor1;
public event ProcessingFor2 ProcessingEventFor2;


private void handlerProcessing1Event(string filename) {
  Console.WriteLine("Processing 1: " + filename);
  ProcessingEventFor1(filename);
}

private void handlerProcessing1Event(string filename) {
  Console.WriteLine("Processing 2: " + filename);
  ProcessingEventFor2(filename);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

┈┾☆殇 2024-11-11 15:04:14

您的 UI 未更新的原因是主 UI 线程卡在 while() 循环中。 BackgroundWorker 是你的朋友,

尝试避免在一个线程中创建线程并坐在那里等待它们完成,这首先是对线程的错误使用,

欢呼

the reason your UI is not updating is that the primary UI thread is stuck in your while() loop. BackgroundWorker is your friend

try to avoid creating threads in one thread and sit there waiting for them to finish, its a bad use of threads in the first place

cheers

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文