1

いくつかのスレッドを開始する次のコードがあります。

    List<Stuff> lNewStuff = new List<Stuff>();

    // populate lNewStuff

    for (int i = 0; i < accounts.Length; i++)
    {
        Account aTemp = _lAccounts.Find(item => item.ID == accounts[i]);

        Thread tTemp = new Thread(() => aTemp.ExecuteMe(lNewStuff));
        tTemp.Start();     
    }

次に、Accountクラスに、ロックのあるExecuteMeメソッドがあります。

    public class Account
    {
        private Object lockThis = new Object();

        public void ExecuteMe(List<Stuff> lNewStuff)
        {
            //Ensure only one thread at a time can run this code
            lock (lockThis)
            {
                //main code processing
            }
        }
    }

これで、スレッドがlNewStuff == nullで始まる場合があります。これは、アカウントIDを持つ新しいものが見つからない場合があるためです。これは、このプロジェクトでは正常です。スレッドは常に実行を試みる必要がありますが、nullの場合は、このスレッドを終了させ、ロックが発生したときに待機しないようにします。

具体的には:

lNewStuffがnullでロックがある場合は、スレッドを終了します。(これを行う方法?)

lNewStuffがnullでロックがない場合は、通常どおり実行します(これはすでに実行されています)

lNewStuffがnullでなく、ロックがある場合は、ロックが終了するのを待ちます(これはすでに実行されています)

lNewStuffがnullでなく、ロックがない場合は、通常どおり実行します(これはすでに実行されています)

4

3 に答える 3

3

lNewStuffnullの場合、ロックが付与されている場合にのみ使用して続行できますMonitor.TryEnter

public class Account
{
    private readonly object lockThis = new object();

    public void ExecuteMe(List<Stuff> lNewStuff)
    {
        bool lockTaken = false;
        try
        {
            if (lNewStuff == null)
            {
                // non-blocking - only takes the lock if it's available
                Monitor.TryEnter(lockThis, ref lockTaken);
            }
            else
            {
                // blocking - equivalent to the standard lock statement
                Monitor.Enter(lockThis, ref lockTaken);
            }

            if (lockTaken)
            {
                // main code processing
            }
        }
        finally
        {
            if (lockTaken)
            {
                Monitor.Exit(lockThis);
            }
        }
    }
}
于 2013-02-28T04:37:29.937 に答える
0
If lNewStuff is null and there is a lock then terminate the thread. (how to do this?) , 
do you want to still start a thread if lNewStuff is Null if answer is no then solution must be very simple.

List<Stuff> lNewStuff = new List<Stuff>();

// populate lNewStuff

for (int i = 0; i < accounts.Length; i++)
{
    Account aTemp = _lAccounts.Find(item => item.ID == accounts[i]);
   if(lNewStuff!=null)
   {
          Thread tTemp = new Thread(() => aTemp.ExecuteMe(lNewStuff));
          tTemp.Start();   
   }

}
also you shd create a single lock object 
private Object lockThis = new Object(); // this statement is creating new lock object with every account object, and hence does not ensure critical section protection.

これをに変更します

private static Object lockThis = new Object(); 
于 2013-02-28T05:00:13.427 に答える
0

ただ違う:

public class Foo : IDisposable
{
    private Semaphore _blocker;
    public Foo(int maximumAllowed)
    {
        _blocker = new Semaphore(1,1);
    }

    public void Dispose()
    {
        if(_blocker != null)
        {
            _blocker.Dispose();
            _blocker.Close();
        }
    }

    public void LimitedSpaceAvailableActNow(object id)
    {
        var gotIn = _blocker.WaitOne(0);
        if(!gotIn)
        {
            Console.WriteLine("ID:{0} - No room!", id);
            return;
        }
        Console.WriteLine("ID:{0} - Got in! Taking a nap...", id);
        Thread.Sleep(1000);
        _blocker.Release();
    }
}

テストリグ:

void Main()
{
    using(var foo = new Foo(1))
    {
        Enumerable.Range(0, 10)
            .Select(t => 
                Tuple.Create(t, new Thread(foo.LimitedSpaceAvailableActNow)))
            .ToList()
            .AsParallel()
            .ForAll(t => t.Item2.Start(t.Item1));
        Console.ReadLine();
    }
}

出力:

ID:4 - Got in! Taking a nap...
ID:8 - No room!
ID:0 - No room!
ID:7 - No room!
ID:2 - No room!
ID:6 - No room!
ID:5 - No room!
ID:9 - No room!
ID:1 - No room!
ID:3 - No room!
于 2013-02-28T05:17:43.647 に答える