Thread order execution?

2019-02-17 13:47发布

I have this simple code : (which i run in linqpad)

void Main()
{
    for ( int  i=0;i<10;i++)
     {
      int  tmp=i;
      new Thread (() =>doWork(tmp)).Start();
     }
}

 public void doWork( int h)
 {
 h.Dump();
 }

the int tmp=i; line is for capture variable - so each iteration will have its own value.

2 problems :

1) the numbers are not sequential , while thread execution is !

2) sometimes i get less than 10 numbers !

here are some executions outputs:

enter image description hereenter image description hereenter image description hereenter image description here

questions :

1) why case 1 is happening and how can i solve it ?

2) why case 2 is happening and how can i solve it ?

6条回答
混吃等死
2楼-- · 2019-02-17 13:55

The nature of thread management is random. You can solve both task, but overhead is too big.

  1. Problem appears that multiple thread concurs on console (or what you use for dump), overriding of sync mechanism is possible but complicated and will cause reduce of performance
  2. You exit before all threads are invoked (see answer by @Marc Gravell)
查看更多
走好不送
3楼-- · 2019-02-17 13:56

Threads execute in unpredictable order, and if the main thread finishes before others you'll not get all the numbers (dump() will not execute). If you mark your threads as IsBackground = false you'll get them all. There's no real solution for the first one except not using threads (or joining threads, which is same thing really).

查看更多
放荡不羁爱自由
4楼-- · 2019-02-17 14:04

You shouldn't expect any ordering between threads.

If you start a new thread, it is merely added to the operating system's management structures. Eventually the thread scheduler will come around and allocate a time slice for the thread. It may do this in a round-robin fashion, pick a random one, use some heuristics to determine which one looks most important (eg. one that owns a Window which is in the foreground) and so on.

If the order of the outputs is relevant, you can either sort it afterwards or - if you know the ordering before work begins already - use an array where each thread is given an index into which it should write its result.

Creating new threads the way your example does is also very slow. For micro tasks, using the thread pool is at least one order of magnitude faster.

查看更多
爱情/是我丢掉的垃圾
5楼-- · 2019-02-17 14:06

It should not be expected that they are sequential. Each thread gets priority as the kernel chooses. It might happen that they look sequential, purely by the nature of when each is started, but that is pure chance.

For ensuring that they all complete - mark each new thread as IsBackground = false, so that it keeps the executable alive. For example:

new Thread(() => doWork(tmp)) { IsBackground = false }.Start();
查看更多
趁早两清
6楼-- · 2019-02-17 14:09

You can order thread execution, but it has to be done specifically by you for the specific problem with a specific solution.

E.g.: you would like that thread 1,2,3 complete phase 1 of your code, and then they proceed to the next phase in the order of their IDs (these IDs you have assign).

You can use semaphores to achieve the behavior - search for block synchronization and mutual exclusion and Test-and-set method.

查看更多
来,给爷笑一个
7楼-- · 2019-02-17 14:22

if ordering is important you may want to avail of a shared queue and use a semaphore to ensure only one thread operates on the top of the queue at a time

查看更多
登录 后发表回答