5

以下のメソッドは、最初の呼び出しでは true を返し、それ以外の呼び出しでは false を返す必要があります。

問題はありますか?ロックにリセットイベントを使用しても安全ですか?

private ManualResetEvent _resetEvent = new ManualResetEvent(false);

public bool AmIFirst()
{
    lock (_resetEvent)
    {
        bool first = !_resetEvent.WaitOne(0);
        if (first)
            _resetEvent.Set();

        return first;
    }
}

編集:あなたの発言を確認した後、いくつかの変更を加えました。ManualResetEvent以前のデザイン案で行き詰まりました。私は実際にはそれをまったく必要としません。

class ActionSynchronizer
{
    private Timer _expirationTimer;
    private object _locker = new object();
    private bool _executionRequired = true;

    private SomeDelegate _onExpired = delegate { };

    public ActionSynchronizer(SomeDelegate onExpired)
    {
        _onExpired = onExpired;
        expirationTimer = new Timer(OnExpired, null, 30000, Timeout.Infinite);
    }

    public bool IsExecutionRequired()
    {
        if (!_executionRequired)
            return false;

        lock (_locker)
        {
            if (_executionRequired)
            {
                _executionRequired = false;
                return true;
            }

            return false;
        }
    }

    private void OnExpired(object state)
    {
        if (_executionRequired)
        {
            lock (_locker)
            {
                if (_executionRequired)
                {
                    _executionRequired = false;
                    // http://stackoverflow.com/questions/1712741/why-does-asynchronous-delegate-method-require-calling-endinvoke/1712747#1712747
                    _onExpired.BeginInvoke(_originalAction, EndInvoke, null);
                }
            }
        }
    }
}

// ...
{
    if (_action.Sync.IsExecutionRequired())
        _action.Invoke();
}
4

4 に答える 4

14

ここは別ルートで行きますが…

private int counter;
...
if(Interlocked.Increment(ref counter) == 1)
{
     // yes, I'm first
}

スレッドセーフ、ロックなし。または、Int32 をラップすることが心配な場合は、次のようにします。

if(Interlocked.CompareExchange(ref counter, 1, 0) == 0)
{
     // yes, I'm first
}   
于 2011-03-21T09:28:19.847 に答える
0

確認する必要があるのは、ロックする同じオブジェクトが、同期が必要なコードのすべてのインスタンスにアクセスできることだけです。それ以外は問題ありません。

于 2011-03-21T09:16:10.593 に答える