【发布时间】:2013-07-12 19:37:58
【问题描述】:
以下是我使用的代码。主线程等待线程池线程执行。我使用 AutoResetEvent (WaitHandle),但我真的很惊讶我偏离了标准,因为代码没有按预期运行。
我有两个同心的for循环,其中Threadpool在内部循环中,并且预计对于外部循环的每次迭代,都应该处理所有内部循环值。使用 AutoResetEvent WaitOne 在内部循环外部调用使主线程等待,这是一个静态变量,在外部循环的每次迭代中重置为内部循环的最大值,并在使用 Threadpool 线程的方法调用中使用 Interlock 递减为 AutoResetEvent 调用 Set。但是,即使我希望静态变量在每个内部循环之后显示值 0,它也不会。我的代码有什么问题,我有什么更好的选择来完成任务?事实上,由于值的混淆,主线程似乎并没有真正在等待线程池线程。
using System;
using System.Threading;
namespace TestThreads
{
class Program
{
private static int threadingCounter = 0;
private static readonly object lockThreads = new Object();
private AutoResetEvent areSync = new AutoResetEvent(true);
// <param name="args"></param>
static void Main(string[] args)
{
Program myProgram = new Program();
try
{
try
{
for (int outer = 0; outer < 1000; outer++)
{
threadingCounter = 500;
try
{
for (int inner = 0; inner < 500; inner++)
{
ThreadPool.QueueUserWorkItem(new
WaitCallback(myProgram.ThreadCall), inner);
}
}
catch (Exception ex)
{
Console.WriteLine("Exception :: " + ex.Message);
}
finally
{
myProgram.areSync.WaitOne();
}
if(threadingCounter != 0)
Console.WriteLine("In Loop1, Thread Counter :: " +
threadingCounter);
}
}
catch (Exception ex)
{
Console.WriteLine("Exception :: " + ex.Message);
}
}
catch(Exception ex)
{
Console.WriteLine("Exception :: " + ex.Message);
}
finally
{
threadingCounter = 0;
if (myProgram.areSync != null)
{
myProgram.areSync.Dispose();
myProgram.areSync = null;
}
}
}
public void ThreadCall(object state)
{
try
{
int inner = (int)state;
Thread.Sleep(1);
}
catch (Exception ex)
{
Console.WriteLine("Exception :: " + ex.Message);
}
finally
{
Interlocked.Decrement(ref threadingCounter);
if (threadingCounter <= 0)
areSync.Set();
}
}
}
}
【问题讨论】:
-
你的异常处理太糟糕了。至少有一个错误可见,您没有正确使用 Interlocked.Decrement。您必须使用它的返回值并且从不在变量递减时直接使用它。使用 CountDownEvent 跌入成功的坑。
-
@HansPassant,你的评论很粗鲁,实际上不准确。
-
好吧,我被欺负而改写了。您的异常处理大大提高了代码的可读性。访问被其他线程修改的变量不是问题。更好?
-
@HansPassant,谢谢你的评论,当你说对了的时候不必被欺负,我知道异常处理很糟糕,但请注意我粘贴了我添加的代码尝试最终从各个方面赶上,重点是了解线程同步的问题并确保进行正确的调用,尽管我从未添加过干净的专业代码。但是,当您提出这样的建议时,请至少提供一个您认为很好的异常处理示例,因为这将有助于更好地理解您的观点,谢谢,
-
@Tyler Jensen 感谢您的评论,但到目前为止,HansPassant 的建议有效,我能够更正代码。但是,如果在多线程方案中对异常处理有任何好的做法,请提出建议。
标签: c# .net multithreading threadpool