2011-05-02 38 views
0

我有1类(acBL)处理2线程(fpDoWork)。任何在fpDoWork中完成的工作都会触发一个返回到acBL类的事件。在我的表单中,我声明了acBL类,并在acBL上关联了事件处理程序 - 这样,无论何时调用该事件,它都应该用更改更新UI。使用BeginInvoke挂起UI更新直到线程完成?

不会发生的情况是,当每个fpDoWork线程启动时,它执行操作,调用ProcessingEvent并进入frmMain.handlerProcessing1事件。它会调用this.BeginInvoke(new Processing2Event(handlerProcessing2),status),然后它会挂起并等待线程完成工作,然后再继续更新UI。我试过这个.Invoke,但是这种方法似乎只是悬而未决。有任何想法吗?

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

在主方法:

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"); 
内部frmMain

在代码早些时候

代码

否则在代码:

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); 
} 
+2

您希望通过创建僵局阻止UI线程,在标志上循环。 BeginInvoke目标无法运行,直到UI线程空闲,回到抽取消息循环。你应该永远不会阻止UI线程。 避免重新发明伤害,请使用BackgroundWorker。并且不要在其IsBusy属性上循环,同样的问题。在RunWorkerCompleted事件处理程序中的线程完成后,执行任何您想要执行的操作。 – 2011-05-02 01:12:01

+0

我没有时间重新编码以合并BackgroundWorker。我确实尝试过实施它,但发现有限制。有没有办法在这种情况下解决死锁? – user723217 2011-05-02 02:44:06

+0

汉斯的评论是正确的。修复死锁需要时间。我第二次提出他的动议,你花时间正确地解决问题。任何被黑客入侵的解决方案(例如嵌套的消息循环)只会导致您未来处理的奇怪错误;它会为您节省大量的时间来提前修复它,而不是稍后修复它。 – 2011-05-02 02:57:14

回答

0

你的UI没有更新的原因是主UI线程停留在你的()循环。 BackgroundWorker的是你的朋友

尽量避免在一个线程创建线程,坐在那里等着他们去完成,它的坏使用线程摆在首位

欢呼

相关问题