-3

トップノート:コメントごとに、このメモですべてが機能していると推測できます。実際、私のアプリケーションでは、それらを組み合わせようとしています。ちなみに、反対票を投じる前に、詳細を尋ねることができます。

トップノート 2: ところで、SO は MSO の反対票やクローズ票とは異なり、質問の削除を奨励するため、そうしません。そうしないと、すべての貴重なコメントと回答が削除されます。ここは助け合い、お互いを理解しようとする場所です

これは、linqpad コードの 4 つの異なる実装のうち最も基本的なものです。最初を除いて、他のすべてが望ましい出力を提供します。

詳細を説明していただけますか?

アプリケーションに多くのタイマーがあるため、完全なコードで管理および同期する必要があります。

SynchronizingObject もタイマー停止/開始もロックもなし

System.Timers.Timer timer2 = new System.Timers.Timer(100);
int i = 0;
void Main()
{
    timer2.Elapsed += PromptForSave;
    timer2.Start();
}

private void PromptForSave(Object source, System.Timers.ElapsedEventArgs e)
{
    i = i + 1;
    Thread.Sleep(new Random().Next(100, 1000));
    Console.WriteLine(i);
}

与えます:

4 5 6 7 8 9 11 12 13 14 15 15 15 17 18 20 21 22


SynchronizingObject の場合:

void Main()
{
    timer2.Elapsed += PromptForSave;
    timer2.SynchronizingObject = new Synchronizer();
    timer2.Start();
}

private void PromptForSave(Object source, System.Timers.ElapsedEventArgs e)
{
    i = i + 1;
    Thread.Sleep(new Random().Next(100, 1000));
    Console.WriteLine(i);
}

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20


タイマー付 スタート/ストップ

void Main()
{
    timer2.Elapsed += PromptForSave;    
    timer2.Start();
}

private void PromptForSave(Object source, System.Timers.ElapsedEventArgs e)
{
    timer2.Stop();
    i = i + 1;
    Thread.Sleep(new Random().Next(100, 1000));
    Console.WriteLine(i);
    timer2.Start();
}

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20


最後にロック付き

object lockForTimer = new object();
void Main()
{
    timer2.Elapsed += PromptForSave;    
    timer2.Start();
}

private void PromptForSave(Object source, System.Timers.ElapsedEventArgs e)
{
    lock(lockForTimer){
        i = i + 1;
        Thread.Sleep(new Random().Next(100, 1000));
        Console.WriteLine(i);
        timer2.Start();
    }
}

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

シンクロナイザーは次のようになります。

public class Synchronizer : ISynchronizeInvoke
{
    private Thread m_Thread;
    private BlockingCollection<Message> m_Queue = new BlockingCollection<Message>();

    public Synchronizer()
    {
        m_Thread = new Thread(Run);
        m_Thread.IsBackground = true;
        m_Thread.Start();
    }

    private void Run()
    {
        while (true)
        {
            Message message = m_Queue.Take();
            message.Return = message.Method.DynamicInvoke(message.Args);
            message.Finished.Set();
        }
    }

    public IAsyncResult BeginInvoke(Delegate method, object[] args)
    {
        Message message = new Message();
        message.Method = method;
        message.Args = args;
        m_Queue.Add(message);
        return message;
    }

    public object EndInvoke(IAsyncResult result)
    {
        Message message = result as Message;
        if (message != null)
        {
            message.Finished.WaitOne();
            return message.Return;
        }
        throw new ArgumentException("result");
    }

    public object Invoke(Delegate method, object[] args)
    {
        Message message = new Message();
        message.Method = method;
        message.Args = args;
        m_Queue.Add(message);
        message.Finished.WaitOne();
        return message.Return;
    }

    public bool InvokeRequired
    {
        get { return Thread.CurrentThread != m_Thread; }
    }

    private class Message : IAsyncResult
    {
        public Delegate Method = null;
        public object[] Args = null;
        public object Return = null;
        public object State = null;
        public ManualResetEvent Finished = new ManualResetEvent(false);

        public object AsyncState
        {
            get { return State; }
        }

        public WaitHandle AsyncWaitHandle
        {
            get { return Finished; }
        }

        public bool CompletedSynchronously
        {
            get { return false; }
        }

        public bool IsCompleted
        {
            get { return Finished.WaitOne(0); }
        }
    }
}
4

1 に答える 1