循环和等待线程中的多线程 WinForms 和 C#
我对这段代码遇到了麻烦。我正在使用 .Net (C#) 和 Winform 应用程序。
我需要运行 RunProgram 方法,该方法具有调用名为 ListLoop 的方法的循环。 在此函数中,有一个 forach 为列表中的每个元素创建 1 个线程。
(请先阅读代码,然后再继续阅读说明,以便您能够理解我在说什么)
问题是,如果我不在“for”(RunProgram 方法)中进行任何控制,它会启动(当然)10 次列表循环函数。 所以我会在“For”中添加一个等待所有线程终止的代码,这样我就可以做一些事情,然后继续下一个循环。
我尝试了 thread.join() 但它冻结了我的 UI 应用程序 (它的应用程序里面有一个WebControl浏览器)。
即使我尝试使用 returnThred 和 thread.isAlive,它仍然会冻结 UI。
如果我没有多线程,我就不会留在这里解决这些问题,但我认为这是我的程序唯一好的解决方案。
我的代码有简单的解决方案吗? 更新:也许我的问题不清楚。
我只想运行 ListLoop X 次,但在开始下一个之前,我想等待所有线程都已死亡(第一次调用的线程),以便我可以进行一些控制并继续 RunProgram 内的循环。
Update2 我有这个 UI 应用程序,它有一个 WebBrowser 控件。我有一个链接对象列表(此类的每个元素都有字符串 url 和 idHost =1 2 3 4...1 for google 2 for yahoo 等...) 我想创建一个循环,让我的程序为列表的每个元素启动一个 newTab (使用方法 AddTab(url) )。当所有链接都打开时(因此所有线程都死了),我需要执行一些操作来计算打开的页面数以及 idHost 是谁,保存它并使用列表启动另一个循环(此列表从更大的列表中获取随机元素) )
更新 3 我刚刚尝试使用 BackGround Worker 但无法使用它,因为我正在使用的 WebKit 给出了 COM 错误。任务的一些东西。
谢谢
private void RunProgram()
{
List<Links> TheList = new List<Links>();
//Do something to Populate the List
List<System.Threading.Thread> returnThread = new List<.....>();
for(int i=0; i<10; i++)
{
returnThread=ListLoop(TheList);
// ???????????
// When Loop Method has finished and all threads stopped
// Do something
// Continue for the next Loop
}
}
private List<System.Threading.Thread> ListLoop(List<Links> list)
{
List<System.Threading.Thread> threading = new List<System.Threading.Thread>();
foreach (Links link in list)
{
Links tmp = new Links();
tmp = link;
var thread = new System.Threading.Thread(p =>
{
lock (l)
{
Action action = () =>
{
AddTab(tmp);
};
this.Invoke(action);
if (tmp.idHost == 1) //if IDhost == Google wait 5sec
{
System.Threading.Thread.Sleep(5000);
}
else
{
System.Threading.Thread.Sleep(2000);
}
}
});
threading.Add(thread);
thread.Start();
}
return threading;
}
I'm in trouble with this code. I'm using .Net (C#) with Winform Application.
I need to run RunProgram Method which has loop that make a call to a method named ListLoop.
In this function there is a forach that creates 1 thread for each element a list.
(Please Read the code before continue to read the description so you could understand what i'm talking about )
The problem is that if i dont make any control in the "for" (RunProgram Method) it starts (of course) 10 times The ListLoop Function.
So i would add in that "For" a code which wait that all Threads are terminated, so i can do Something and Then continue with the next loop.
I tried thread.join() but it freeze my UI application
(it's Application which inside has a WebControl Browser).
Even if i Try to play with returnThred and with thread.isAlive it still freezes UI.
If i hadn't the Multithread i'll dont stay here with those problems but it's the only good solution for my program i think.
Is there a simple solution for my code?
Update: Maybe it'snt clear my question.
I just want run the ListLoop X times but before start the next one i want wait that all threads are dead (That ones of the first call) so i can do some control and continue with the loop inside RunProgram.
Update2 I have this UI application which has a WebBrowser Control. I have a List of Links Object (each element of this class has string url and idHost =1 2 3 4...1 for google 2 for yahoo etc...)
I want make a loop where my program start a newTab (with Method AddTab(url) ) for each element of the list. When all links are opened (and so all the threads are deads and) i need to do something that count how many pages opened and who was the idHost save it and start another Loop with the list(This list take random element from a Bigger List)
Update 3 I just tried with BackGround Worker but i cant use it cause the WebKit that i'm using give COM error. Something for the Tasks.
Thanks
private void RunProgram()
{
List<Links> TheList = new List<Links>();
//Do something to Populate the List
List<System.Threading.Thread> returnThread = new List<.....>();
for(int i=0; i<10; i++)
{
returnThread=ListLoop(TheList);
// ???????????
// When Loop Method has finished and all threads stopped
// Do something
// Continue for the next Loop
}
}
private List<System.Threading.Thread> ListLoop(List<Links> list)
{
List<System.Threading.Thread> threading = new List<System.Threading.Thread>();
foreach (Links link in list)
{
Links tmp = new Links();
tmp = link;
var thread = new System.Threading.Thread(p =>
{
lock (l)
{
Action action = () =>
{
AddTab(tmp);
};
this.Invoke(action);
if (tmp.idHost == 1) //if IDhost == Google wait 5sec
{
System.Threading.Thread.Sleep(5000);
}
else
{
System.Threading.Thread.Sleep(2000);
}
}
});
threading.Add(thread);
thread.Start();
}
return threading;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果从主应用程序调用 RunProgram,如果它休眠或等待线程终止,它将冻结您的主窗体。您应该在其自己的线程中运行 RunProgram 方法,以便它可以创建工作线程,然后您可以等待线程在 for 循环中完成,然后再启动新线程。
您可以使用 AutoResetEvent 在线程完成时发出信号,以便您只需在继续循环之前等待 AutoResetEvent 即可。 BackgroundWorker 类可能是一个值得一看的好类也用于创建您的线程。
If
RunProgram
is called from your main application, it will freeze your main form if it sleeps or waits for threads to terminate. You should run theRunProgram
method in its own thread, so it can then create the worker threads, and then you can wait for the threads to complete in your for loop before starting new ones.You could use AutoResetEvent to signal when threads are finished so you can simply wait on the AutoResetEvent before continuing the loop. The BackgroundWorker class may be a good class to look at for creating your threads as well.
我不确定我是否正确理解了你的问题,但是:
你在这里异步工作......你不能在不停止 GUI 的情况下在代码中等待。
我认为你的解决方案是将你的函数分成两部分——你刚刚编写的第一部分,第二部分在线程全部死掉后工作。
对于第二部分(检查线程),如果您想保存线程并轻松集成到主窗体中,我将使用另一个线程(等待线程死亡而不是继续执行您的代码)或计时器
更新:
下面是一个不阻塞 GUI 线程的阻塞函数如何
启动该进程的示例:button1。请注意,您必须在处理事件后调用该函数才能将控件移动到主 GUI 线程
希望这会有所帮助
I'm not sure if I understood your question properly, but:
You work asynchronously here... You can't wait in your code without stopping the GUI.
I think your solution will be to separate your function into 2 parts - The 1st one you just written, and the second one works after the threads are all dead.
For the second part (check the threads) I'd use either another thread (That waits until the threads are dead than continues to your code) or a Timer if you'd like to save threads and integrate easily into the main form
UPDATE:
Here is an example of how a blocking function that doesn't block the GUI thread:
button1 starts the process. Notice that you have to invoke the function after the event is handled to move the control to the main GUI thread
Hope this helps