在同一线程上运行的两个事件处理程序之间的同步

时间:2017-08-05 07:58:26

标签: c# events synchronization

非常感谢您在建议解决以下问题时的帮助。

问题描述: 在我的应用程序中,我在同一个线程上接收两个事件,两个事件处理程序都调用一个执行某项任务并在其中调用Application.DoEvents()的方法。

当我收到Event1时,它调用Event1_Handler,它调用DoWork。在DoWork中,我们调用Application.DoEvents()并等待循环达到.5秒,然后在线程泵中执行其他挂起事件,然后调用其他线程启动。 我们离开了'#34; Some Work"完成或我们等待.5秒然后离开任何方式。

所以来自Event1_Handler的DoWork尚未完成,同时收到Event2,它调用实时调用DoWork的Event2_Handler。这会产生不良行为。

这些事件总是按顺序排列,但可以在几毫秒之后发生。

using System;
using LoggerSpace;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;
namespace SyncMech
{
    public delegate void MyDel();
    public partial class Form1 : Form
    {
        event MyDel Event1;
        event MyDel Event2;
        public Form1()
        {
            InitializeComponent();

            // Some logger initialization stuff
            Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
            Trace.AutoFlush = true;
            Trace.Indent();
        }

        private void Event2_Handler()
        {
            Logger.LogThisLine(">>> Event2_Handler");
            DoWork();
            Logger.LogThisLine("<<< Event2_Handler");
        }

        private void Event1_Handler()
        {
            Logger.LogThisLine(">>> Event1_Handler");
            DoWork();
            Logger.LogThisLine("<<< Event1_Handler");
        }
        public void DoWork()
        {
            Logger.LogThisLine(">>> DoWork");
            for (int i = 0; i < 5; i++)
            {

                // We get out of loop after 500 ms or when Heavy work is completed
                // completion of heavy work is notified by event hence Application.DoEvents is needed
                Logger.LogThisLine("Heavy work");
                Application.DoEvents();
                Thread.Sleep(100);
            }
            Logger.LogThisLine("<<< DoWork");
        }
        public void RaiseEvents()
        {
            Event1.Invoke();

            // have difference of 20 ms between both events
            Thread.Sleep(20);

            Event2.Invoke();
        }
        private void button2_Click(object sender, EventArgs e)
        {
            // Created a simple UI app with only one button
            // Registered Event1 and Event2
            this.Event1 += () => this.BeginInvoke((MethodInvoker)Event1_Handler);
            this.Event2 += () => this.BeginInvoke((MethodInvoker)Event2_Handler);

            // Raise both the events from background thread
            new Thread(new ThreadStart(RaiseEvents)).Start();
        }
    }
}

输出:

8/5/2017 7:45:43 PM :   >>> Event1_Handler  
8/5/2017 7:45:43 PM :   >>> DoWork  
8/5/2017 7:45:43 PM :   Heavy work  
8/5/2017 7:45:43 PM :   Heavy work  
8/5/2017 7:45:43 PM :   >>> Event2_Handler  
8/5/2017 7:45:43 PM :   >>> DoWork  
8/5/2017 7:45:43 PM :   Heavy work  
8/5/2017 7:45:44 PM :   Heavy work  
8/5/2017 7:45:44 PM :   Heavy work  
8/5/2017 7:45:44 PM :   Heavy work  
8/5/2017 7:45:44 PM :   Heavy work  
8/5/2017 7:45:44 PM :   <<< DoWork  
8/5/2017 7:45:44 PM :   <<< Event2_Handler  
8/5/2017 7:45:44 PM :   Heavy work  
8/5/2017 7:45:44 PM :   Heavy work  
8/5/2017 7:45:44 PM :   Heavy work  
8/5/2017 7:45:44 PM :   <<< DoWork  
8/5/2017 7:45:44 PM :   <<< Event1_Handler  

这是一个非常古老的应用程序,DoWork是从这个应用程序的多个模块调用的,如果变更会产生很大的影响。我知道需要在Event_Handler2中完成的工作需要在Event_Handler1之后完成。当锁定在同一个线程上时,锁定不起作用。

问题:我如何确保Event_Handler2仅在Event_Handler1处理完成后才执行。还有其他任何建议。

0 个答案:

没有答案