基本上我有一个带按钮的表单,当按下按钮时,它会创建一个运行Thread的类的实例。线程完成后,它会自动调用Thread.Abort()。
我目前的代码归结为:
按钮:
private void Buttonclick(object sender, EventArgs e)
{
MyClass c = new MyClass()
c.Do_your_thing();
}
类别:
public class MyClass
{
Thread t;
public void Do_your_thing()
{
t = new Thread(Running_code);
t.Start();
}
private void Running_code()
{
//Perform code here
t.Abort();
}
}
当我单击按钮一次时,一切正常。但是当我再次按下按钮时,没有任何反应。
当我不使用t.Abort()时一切正常。但是不使用t.Abort()将导致内存泄漏,程序将无法正常关闭(线程永远不会关闭,因此进程将保持活动状态)。
任何人都可以解释一下发生了什么吗?我该如何解决?
编辑:根据要求,我发布了一些实际代码
public class MyClass
{
public void Test()
{
t = new Thread(() =>
{
wb.DocumentCompleted += get_part;
wb.Navigate("http://www.google.com");
Application.Run();
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
public void get_part(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var br = sender as WebBrowser;
string url = e.Url.ToString();
//Here is some code that compares the url to surten predefined url. When there is a match, it should run some code and then go to a new url
if(url == string_final_url)
{
//Finally at the url I want, open it in a new Internet Explorer Window
Process proc = Process.Start("IExplore.exe", url);
}
}
}
这是一个小型webscraper计划的一小部分。它导航到需要一些登录信息的网页。当我到达我真正想要的页面时,他应该在新的Internet Explorer中打开它。
当我调用此代码并关闭表单时,它仍然可以在进程树中看到。当我多次单击该按钮时,使用的内存不断增加,我怀疑是某种内存泄漏。
答案 0 :(得分:2)
首先,不要使用Thread.Abort()
。有关原因的详细信息,请参阅Is this thread.abort() normal and safe?。
关于使用Thread.Abort()
,There are many warnings all over the net。我会建议避免它,除非它真的需要,在这种情况下,我不认为它。你最好只实现一次性定时器,可能有半秒钟的超时,并在每次按键时重置它。这样,您的昂贵操作只会在用户不活动的半秒或更长时间(或您选择的任何长度)之后发生。
您可以使用Join()
Method而不是使用中止。此方法阻塞调用线程,直到线程终止。
使用它的一个例子是
Thread t1 = new Thread(() =>
{
Thread.Sleep(4000);
Console.WriteLine("t1 is ending.");
});
t1.Start();
Thread t2 = new Thread(() =>
{
Thread.Sleep(1000);
Console.WriteLine("t2 is ending.");
});
t2.Start();
t1.Join();
Console.WriteLine("t1.Join() returned.");
t2.Join();
Console.WriteLine("t2.Join() returned.");
我希望这会有所帮助。
修改的。解决你的意见;对Join()的调用是取消分配线程的内容。你不必做任何其他事情。只需确保线程在退出之前清理它们可能正在使用的任何资源。
那就是说,我建议你研究使用线程池或任务并行库(TPL)而不是显式管理线程。它们更容易使用,并且更加顺畅地处理这类事情。
答案 1 :(得分:1)
你是否能够使用.net 4 +如果是这样你可以使用TPL,这会大大简化这个
public class MyClass
{
public void Do_your_thing()
{
// for async execution
Task.Factory.StartNew(Running_code);
// for synchronous execution
// CAUTION !! If invoked from UI thread this will freeze the GUI until Running_code is returned.
//Task.Factory.StartNew(Running_code).Wait();
}
private void Running_code()
{
Thread.Sleep( 2000 );
Debug.WriteLine( "Something was done" );
}
}
此外,如果Running_Code方法正在执行IO绑定,则TPL可以使用IO完成端口,并且操作可以完全无线程。
编辑:
看看这个SO线程。 WebBrowser Control in a new thread。
显然,对于非UI线程,webbrowser控件不能很好地运行。