2010-08-06 35 views
0

我有一个小问题,与此代码:参数过路线程C#ERROR

这是应用程序的“主”的方法:

private Thread main_process; 
private Clases.GestorTR processor; 

public void begin() 
{ 
    processor = new Clases.GestorTR(); 
    main_process = new Thread(new ThreadStart(processor.ExecuteP)); 
    main_process.Start(); 
} 

我创建了一个线程来处理其他“Transacction Threads”避免阻塞GUI。 这是方法ExecuteP,处理器对象上:

public void ExecuteP() 
{ 
// Readed an DataTable with BD transacction, filled with numbers 
foreach (DataRow dr in dtResults.Rows) 
{ 
    int Local_number = Convert.toInt32(dr["autonum"].ToString()); 
    ThreadStart starter; 
    starter = delegate { new QueryBD.QueryCounter(Local_number); }; 
    new Thread(starter).Start(); 
} 
} 

这是QueryBD类的QueryCounter方法:

.... 
private void QueryCounter(int _counter) 
    { 
     logs.log("ON QUERY_PROCESS: " + _counter); 
    } 
... 

现在,问题。在调用委托时,一些线程正在穿越参数。例如,在foreach方法中,日志显示正确(1,2,3,4,5,6,7,8),但在QueryCounter方法中(每次调用新线程时,日志显示为1,1 ,1,4,5,6,6,8)例如,我也试过使用锁,但问题是一样的,同样使用ThreadPool方法测试,结果相同 我想我错过了东西在foreach循环,因为如果我调试首次运行时,线程启动,但没有在日志中动作

感谢!

回答

0

你应该尝试改变你的代码是一样的某些部分:

public void ExecuteP() 
{ 
    QueryBD facade = new QueryBD. 
    foreach (DataRow dr in dtResults.Rows) 
    { 
    int Local_number = Convert.toInt32(dr["autonum"].ToString()); 
    new Thread(new ParameterizedThreadStart(facade.QueryCounter)).Start(Local_number); 
    } 
} 

public void QueryCounter(object _counter) 
{ 
    ... 
} 

希望它有效。

Btw。我创建了一个名为Facade的对象,并将该对象传递给各个线程。它也可以导致一些副作用,是否会有线程在外观对象代码敏感的部分,所以你也可以考虑锁定有:

public void QueryCounter(object _counter) 
{ 
    lock(this) 
    { 
     // 
    } 
} 

或给每个线程提供新QueryBD,但它可能会影响性能。

编辑:喂,4两件事:

  1. 在使用ParametrizedThread,通过了可变启动线程(thread.Start(variable))在呼叫的时间被复制的方法。这个复制的变量然后在子线程中使用。匿名代理工作不同。它保持对变量的引用,所以当变量被子线程使用时,它可以通过父线程中的时间进行更改。这就是为什么你有不可预知的行为。

  2. 更好的解释你可以在这里找到:Differing behavior when starting a thread: ParameterizedThreadStart vs. Anonymous Delegate. Why does it matter?

  3. 性能取决于。如果你的对象的创建过程很繁琐(例如,它会在每次创建时创建与数据库的新连接),那么创建很多这样的对象会严重影响性能 - 这就是锁定更好的地方。如果创建对象很轻,则可以根据需要创建任意数量的对象。这取决于。

  4. 如果您希望您的代码按照定义的顺序运行,则根本不应该使用线程。如果要保留执行顺序,顺序调用是正确的方法 - 请参阅Hans Passant解释。

+0

嗨!我没有使用ParameterizedThreadStart来获得一个“更干净”的代码,并避免像字符串数组那样解析对象来获取所有参数,但是我错了。现在,我正在研究为什么ThreadPool和委托匿名方法不起作用,有什么想法? 关于锁,性能如何:USING LOCK with 1 base object VS.为每个线程提供一个新实例?思考速度,每次提供新实例并不是更快的方法? 非常感谢, – Jabab 2010-08-06 21:57:50

+0

使用WS调用和BD访问的完整流程。速度和多个请求是一个 “必须”: 随着每次调用新的对象: START 16:00:08.8915628 FINISH 16:00:12.0278610 总时间:3.1362982 随着锁定和单碱基对象: START 16 :02:33.3375315 完成16:02:38.9863682 总时间:5.6488367 – Jabab 2010-08-06 22:12:49

+0

嘿,检查编辑部分在我的答案。该评论部分是对此的简要介绍。保重。 – jwaliszko 2010-08-06 23:00:54