简体   繁体   中英

AutoResetEvent in Multi-threading

I have a sample code below which creates multi-thread having a block of code inside lock in separate thread. I abort child-thread if response is null or if autoReset.WaitOne(timeout) elapses the time-span so that allowing next waiting thread in queue to enter the lock and carryout the operations. But the problem here is if say ThreadA takes 8 seconds to execute the complex code inside lock then the next waiting thread say ThreadB is left with only 2secs (since the AutoResetEvent's wait time for all the threads were started at same time).

How can i make each thread to get same timespan to execute the complex block of code. I'm trying to solve this from past 2 days now, Any inputs will be really helpful.

Class A
{
    static void Main(){
     for(int i=0; i < 2; i++)
      {
        var mainThread = new Thread(ParentThreadMethod);
        mainThread.Start();
      }
    }

    void ParentThreadMethod(){
      var autoReset = new AutoResetEvent(false);
      ClassB obj;
      var childThread = new Thread(() =>
        {
            obj = new ClassB();
            var result = obj.ChildThreadMethod();
            autoReset.Set();
        }       
         childThread.Start();

         // wait for 10sec
         autoReset.WaitOne(10000);           
    }
 } 

 Class B
 {
    private static readonly object threadLock = new object();
    string ChildThreadMethod(){
     lock (threadLock)
            {
                // complex logic taking 8sec 
            }
    }
 }

I think the problem is that both threads share access to

private static readonly object threadLock = new object();

This means that the 2nd thread will spend 8sec waiting for the first to exit the critical region. This makes it look like the timeout is hitting early. But the timeout is working correctly.

It looks like you want to start the timeout only when the lock is successfully entered. This means that the thread itself must start the timeout because only the child thread knows when it entered the lock.

It could look like this:

lock (threadLock) {
    var timeoutTask = Task.Delay(10000);
    var workTask = Task.Run(RunWork);
    var firstTask = Task.WhenAny(timeoutTask, workTask).Result;

    if (!workTask.IsCompleted) {
     AbortWork();
     workTask.Wait(); //Wait for cancellation to finish.
    }
}

Generally the newer TPL features are easier to use than threads and events etc. If this code is new code I'd start over with TPL classes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM