在.NET中有几种方法可以执行异步线程:
System.Threading.Thread.Start()
System.Delegate.BeginInvoke()
我的问题是异步线程在每种情况下都存在于何处?我想在某些情况下避免使用池化线程,因为我正在执行的某些进程需要很长时间,并且会强制使用池化线程。
答案 0 :(得分:4)
运行从Delegate.BeginInvoke
调用的代码的线程与从ThreadPool
类访问的池存在于同一个池中。创建自己的Thread
对象就是这样:创建一个新的(非池化)线程。
以下是一种快速验证方法:创建一个新的Windows窗体应用程序并在窗体上放置两个按钮。包括类似以下代码的内容:
private void ThreadStartButton_Click(object sender, EventArgs e)
{
ThreadPool.SetMaxThreads(4, 4);
for (int i = 0; i < 8; ++i)
{
Thread t = new Thread(ShowMessageBox);
t.Start();
}
}
private void DelegateBeginInvokeButton_Click(object sender, EventArgs e)
{
ThreadPool.SetMaxThreads(4, 4);
for (int i = 0; i < 8; ++i)
{
Action action = ShowMessageBox;
action.BeginInvoke(action.EndInvoke, null);
}
}
private void ShowMessageBox()
{
int threadId = Thread.CurrentThread.ManagedThreadId;
MessageBox.Show(threadId.ToString());
}
当您单击第一个按钮(其处理程序创建新Thread
个对象的按钮)时,您应该会看到一次弹出8个对话框。当您单击第二个(调用BeginInvoke
)时,您应该会看到最多弹出4个对话框。前四次通过单击“确定”关闭其中一个,将弹出另一个对话框(具有相同的线程ID),因为关闭的对话框的线程将返回到池中。
答案 1 :(得分:3)
当您使用Thread.Start()时,该线程与ThreadPool分开。当您使用BeginInvoke(IIRC)时,将调用线程池。与QueueUserWorkItem相同。
答案 2 :(得分:2)
在第一个场景中,他们无处可去。您正在手动创建新线程。在第二个示例中,如果有一个线程可用,则从线程池中抽取一个线程。在长时间运行的操作中,应该避免在大量多线程应用程序(如ASP.NET)中使用线程池中的线程,因为这可能会危及用于服务请求的线程。
基本的经验法则是为长时间运行的操作手动创建线程,但很少(因为创建线程非常耗时)并使用池中的线程进行多次短期操作。
答案 3 :(得分:0)
System.Threading.Thread.Start()
涉及创建不在池中的线程。
System.Delegate.BeginInvoke()
取决于实际的实现,可以是线程池,后台或前台线程。
如果你解释你的情况,我们应该能够提供更多帮助。