C# 这是使用线程池的正确案例吗?
设置如下:我正在尝试制作一个相对简单的Winforms应用程序,一个使用库的提要阅读器。我的问题是关于使用线程池。由于FeedDotNet正在生成同步HttpWebRequests,它正在阻塞GUI线程。因此,最好的方法似乎是将同步调用放在线程池线程上,并在其工作时调用表单上需要更新的控件。一些粗略的代码:C# 这是使用线程池的正确案例吗?,c#,winforms,invoke,threadpool,C#,Winforms,Invoke,Threadpool,设置如下:我正在尝试制作一个相对简单的Winforms应用程序,一个使用库的提要阅读器。我的问题是关于使用线程池。由于FeedDotNet正在生成同步HttpWebRequests,它正在阻塞GUI线程。因此,最好的方法似乎是将同步调用放在线程池线程上,并在其工作时调用表单上需要更新的控件。一些粗略的代码: private void ThreadProc(object state) { Interlocked.Increment(ref updatesPending); // che
private void ThreadProc(object state)
{
Interlocked.Increment(ref updatesPending);
// check that main form isn't closed/closing so that we don't get an ObjectDisposedException exception
if (this.IsDisposed || !this.IsHandleCreated) return;
if (this.InvokeRequired)
this.Invoke((MethodInvoker)delegate
{
if (!marqueeProgressBar.Visible)
this.marqueeProgressBar.Visible = true;
});
ThreadAction t = state as ThreadAction;
Feed feed = FeedReader.Read(t.XmlUri);
Interlocked.Decrement(ref updatesPending);
if (this.IsDisposed || !this.IsHandleCreated) return;
if (this.InvokeRequired)
this.Invoke((MethodInvoker)delegate { ProcessFeedResult(feed, t.Action, t.Node); });
// finished everything, hide progress bar
if (updatesPending == 0)
{
if (this.IsDisposed || !this.IsHandleCreated) return;
if (this.InvokeRequired)
this.Invoke((MethodInvoker)delegate { this.marqueeProgressBar.Visible = false; });
}
}
此
=主窗体实例
updateSpend
=主窗体中的volatile int
ProcessFeedResult
=对提要对象执行某些操作的方法。由于线程池线程不能返回结果,这是通过主线程处理结果的一种可接受的方法吗
我最担心的是它的规模。我一次尝试了250个请求。我看到的最大线程数大约是53个,一旦所有线程都完成了,返回到21个。我记得有一次我玩代码的时候,看到代码高达120。这不正常,是吗?另外,在WindowsXP上,我认为有这么多的连接,在某个地方会有一个瓶颈。我说得对吗
如何确保线程/连接的最大效率
有了所有这些问题,我想知道这是否是线程池使用的正确案例。MSDN和其他消息来源说,它应该用于“短期”任务。考虑到我的连接速度相对较快,1-2秒“短命”是否足够?如果用户使用56K拨号,一个请求可能需要5-12秒甚至更长的时间,该怎么办。那么线程池也是一个有效的解决方案吗?您可能想看看这个课程。我对线程池的理解是,它是为这种情况而设计的。我认为短命的定义是这样的时间顺序——甚至可能长达几分钟。“长寿命”线程应该是在应用程序的生命周期内处于活动状态的线程
别忘了,微软会花一些时间尽可能提高线程池的效率。你认为你能写些更有效率的东西吗?我知道我做不到。线程池,未选中可能是个坏主意 开箱即用,线程池中有250个线程 想象一下,如果在一次突发事件中,你让某人的网络连接变得平坦,并禁止他们从站点获取通知,因为他们被怀疑正在运行DoS攻击 相反,当你从网上下载东西时,你应该建立大量的控制。用户应该能够决定他们发出多少并发请求(以及每个域有多少并发请求),理想情况下,您还希望提供对带宽量的控制
虽然这可以通过线程池进行协调,拥有专用的线程或使用BackgroundWorker类的一些实例是一个更好的选择。NET线程池是专门为执行短时间运行的任务而设计的,创建新线程的开销会抵消创建新线程的好处。它不是为长时间阻塞或执行时间长的任务而设计的 这个想法是为了让一个任务跳到一个线程上,快速运行,完成并跳下 该类提供了一种在线程池线程上执行任务的简单方法,并提供了任务报告进度和处理取消请求的机制 在BackgroundWorker组件中,文件下载被明确给出,作为适当使用此类的示例。这应该会鼓励你使用这个类来完成你需要的工作 如果您担心过度使用线程池,您可以确信运行时会根据需要管理可用线程的数量。任务在线程池中排队等待执行。当一个线程可以执行工作时,任务被加载到该线程上。监视进程定期检查线程池的状态。如果有任务等待执行,它可以创建更多线程。如果有几个空闲线程,它可以关闭一些线程以释放资源
在更糟糕的情况下,如果所有线程都很忙,并且您的工作已排队,则运行时将添加线程以处理额外的工作负载。应用程序将运行得更慢,因为它必须等待更多线程可用,但它将继续运行。几点,并结合信息形成其他一些答案:
- ThreadProc不包含异常处理。您应该添加该选项,否则1个I/O错误将停止进程李>
- Sam Saffron说得很对,你应该限制线程的数量。您可以使用(线程安全)队列将提要推入(工作项),并让1+个线程在循环中读取队列中的内容
- BackgroundWorker可能是个好主意,它将为您提供所需的异常处理和同步
- 后台工作人员使用线程池,这很好