0

タイマーに問題があります。

これは私のコードです:

_uploadHelper = new DataProcessorUploadHelper((sender, args) => Start())

public void Start()
{
        Task.Factory.StartNew(() =>
        {
            if (UploadHelper.UploadState == UploadState.UploadOn)
            {
                UploadHelper.IncrementSavingRequestCounter();
            }
            else
            {
                UploadHelper.StopTimer();
                lock (_lock)
                {
                    UploadHelper.UploadState = UploadState.UploadOn;

                    UploadData();

                    UploadHelper.UploadState = UploadState.UploadOff;
                }
                UploadHelper.StartTimer();
            }
        });
}

UploadState はこのように実装されています

    private int _uploadState;

    public UploadState UploadState
    {
        get { return (UploadState)_uploadState; }
        set { Interlocked.Exchange(ref _uploadState, (int)value); }
    }

System.Timers.Timer を使用しています。これは Start メソッドを 10 分間隔で呼び出す必要があります (ヘルパー クラス内に実装されています)。

    private Timer _intervalTimer;
    private long _savingRequestsCounter;

    public DataProcessorUploadHelper(ElapsedEventHandler callback)
    {
        UploadState = UploadState.UploadOff;;
        _intervalTimer = new Timer();
        _intervalTimer.Interval = UploadIntervalTimeSpan.TotalMilliseconds;
        _intervalTimer.Elapsed += callback;
        _intervalTimer.Start();
        _intervalTimer.Enabled = true;
    } 
    public void StartTimer()
    {
        _intervalTimer.Start();
    }
    public void ResetTimer()
    {
        _intervalTimer.Start();
        _intervalTimer.Stop();
    }

    public void StopTimer()
    {
        _intervalTimer.Stop();
    }
    public void IncrementSavingRequestCounter()
    {
        Interlocked.Increment(ref _savingRequestsCounter);
    }

    public void DecrementSavingRequestCounter()
    {
        Interlocked.Decrement(ref _savingRequestsCounter);
    }

また、このメソッドは、ユーザーが特定のボタンをクリックしたときにも呼び出されます。

そして私の悩み。

タイマーは Start メソッドを呼び出します => UploadHelper.UploadState = UploadState.UploadOn.

また、_lock でロックする必要があります。

しかし、ユーザーが UploadData() 中にクリックすると、 UploadState = UploadState.UploadOff が表示され、ロックされていません。

このコードの何が問題になっていますか?

タイマーがこのメソッドを呼び出すと、状態が異なるのはなぜですか?

4

1 に答える 1

1
  1. 「...さらに_lockでロックする必要があります」

はい、あなたのケースで_lockがstaticとして宣言されている場合。

タイマーの Elapsed-Event が別の Thread で UploadData() の呼び出しを引き起こすため、_lock (静的でない場合) は毎回同じ _lock ではなく、同期オブジェクトとして機能しません。

  1. タイマーが System.Timersからのものである場合、同期する別の方法もあります: SynchronizingObjectを参照してください。
于 2016-03-04T14:36:31.460 に答える