在后台线程火灾事件 [英] Fire Event on Background Thread

查看:135
本文介绍了在后台线程火灾事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我道歉,我不是我的问题和努力准确。我正在开发具有不同的组件控制台应用程序。现在我已经脱钩他们,并希望他们使用异步发布/订阅的方式进行交互他们。类似WPF。因此,在这种情况下,我将有一个主线程,这将永远存在,并根据要求将调用例如事件DataRequested这将在后台线程被解雇。一旦后台线程完成过程中,它会触发事件再次如DataCompleted应该回过头来调用线程,即主线程。我希望我在我解释清楚了。

My apologies I was not accurate in my question and effort. I am developing Console application which has different components. Now I have decoupled them and want them to interact them using asynchronous Publisher/Subscriber way; similar to WPF. So in this case I will have one Master thread which will always be there and depending on request it will invoke event e.g. DataRequested which would be fired on background thread. Once Background thread completes process it will fire event again e.g. DataCompleted which should come back to the calling thread i.e. Master thread. I hope I am clear in my explanation.

So far I have coded below; where I have EventBroker.

 public class EventBroker
    {

        public static event EventHandler SubscriptionAdded;
        public static event EventHandler SubscriptionRemoved;

        private static volatile EventBroker instance;
        private static object syncRoot = new Object();
        private static Dictionary<string, List<Delegate>> subscriptions;

        /// <summary>
        /// Initializes a new instance of the <see cref="T:EventBroker"/> class.
        /// </summary>
        private EventBroker()
        {

        }
        /// <summary>
        /// Gets the instance.
        /// </summary>
        /// <value>The instance.</value>
        public static EventBroker Instance
        {

            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                        {
                            instance = new EventBroker();
                            subscriptions = new Dictionary<string, List<Delegate>>();
                        }
                    }
                }

                return instance;

            }
        }

        /// <summary>
        /// Gets or sets the internal subscriptions dictionary.
        /// </summary>
        /// <value>The subscriptions.</value>

        private static Dictionary<string, List<Delegate>> Subscriptions
        {
            get { return EventBroker.subscriptions; }
            set
            {
                lock (syncRoot)
                {
                    EventBroker.subscriptions = value;
                }
            }
        }


        /// <summary>
        /// Raises the subscription added event.
        /// </summary>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private static void OnSubscriptionAdded(EventArgs e)
        {
            if (SubscriptionAdded != null)
                SubscriptionAdded(instance, e);
        }

        /// <summary>
        /// Raises the subscription removed event.
        /// </summary>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private static void OnSubscriptionRemoved(EventArgs e)
        {
            if (SubscriptionRemoved != null)
                SubscriptionRemoved(instance, e);
        }


        /// <summary>
        /// Subscribe method to the specified event.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <param name="method">The method Delegate to be invoked when Event fires.</param>
        public static void Subscribe(string id, Delegate method)
        {

            //Check if there is a existing event
            List<Delegate> delegates = null;

            if (Subscriptions == null)
                Subscriptions = new Dictionary<string, List<Delegate>>();

            if (Subscriptions.ContainsKey(id))
            {
                delegates = subscriptions[id];
            }
            else
            {
                delegates = new List<Delegate>();
                Subscriptions.Add(id, delegates);
            }


            delegates.Add(method);
            OnSubscriptionAdded(new EventArgs());

        }



        /// <summary>
        /// Unsubscribe method from event notifications
        /// </summary>
        /// <param name="id">The id.</param>
        /// <param name="method">The method.</param>
        public static void Unsubscribe(string id, Delegate method)
        {
            if (Subscriptions.ContainsKey(id))
            {
                if (Subscriptions[id].Contains(method))
                {
                    Subscriptions[id].Remove(method);
                    OnSubscriptionRemoved(new EventArgs());
                }

                if (Subscriptions[id].Count == 0)
                    Subscriptions.Remove(id);

            }
        }


        /// <summary>
        /// Fire the specified event by and pass parameters.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <param name="args">The args.</param>
        public static void Execute(string id, object sender, EventArgs e)
        {
            if (Subscriptions.ContainsKey(id))
            {
                for (int i = 0; i < Subscriptions[id].Count; i++)
                {



                    Delegate x = Subscriptions[id][i];
                    DynamicInvoke(id, x, sender, e);

                    if (!Subscriptions.ContainsKey(id))
                        break;
                }
            }
        }


        /// <summary>
        /// Checks to see if target of invocation is still a valid 
        /// (non-disposed objects). Then it dinamicly invokes Delegate.
        /// </summary>
        /// <param name="id">Event ID</param>
        /// <param name="x">Delegate to invoke</param>
        /// <param name="args">Object array of arguments</param>
        private static void DynamicInvoke(string id, Delegate x, object sender, EventArgs e)
        {



            if (x.Method != null)
            {
                if (x.Target is Control)
                {
                    Control ctl = (Control)x.Target;

                    if (ctl.IsDisposed)
                    {
                        Unsubscribe(id, x);
                        return;
                    }
                }

                if (x.Target == null)
                {
                    Unsubscribe(id, x);
                    return;
                }



                x.DynamicInvoke(sender, e); ***//this becomes blocking call untill EventHandle is completed and hangs Master Thread***

            }
        }
    }

我用这个EventBroker来跟踪我的订阅者,一旦出版商来了,我一定调用委托。但它得到仅在主线程中调用,它被绞死。我想调用事件处理上单独的线程。

I use this EventBroker to keep track of my Subscribers and once Publisher comes I invoke certain delegate. But it gets invoked only on Master thread and it gets hanged. I want to invoke EventHandler on separate thread.

    public class MasterClass
    {
    public MasterClass()
    {


    EventBroker.Subscribe("Topic2", new EventHandler<EventArgs<string>>(CallBackfromWorker));


    }

public void InvokeTest()
    {


EventArgs<string> EventArgs = new EventArgs<string>("Test");
EventBroker.Execute("Topic1", null, EventArgs); //I want both of this to be asynchronous.


    } 
            public void CallBackfromWorker(object sender, EventArgs<string> e)
            {

    Debug.Pring("Get Called Asynchronously from Worker thread through Event");

            }

    }

**//Worker Class**

        public class WorkerClass
        {
            public WorkerClass()
            {
                EventBroker.Subscribe("Topic1", new EventHandler<EventArgs<string>>(HandleRapRequest1));
            }

            public void HandleRapRequest1(string RAPRequest)
            //public void HandleRapRequest1(object sender, EventArgs<string> e)
            {
                Logger.LogToDisplay("WorkerClass Request" + RAPRequest);
                Logger.LogToDisplay("AsyncClient : " + System.Threading.Thread.CurrentThread.IsBackground);
                Logger.LogToDisplay("AsyncClient : " + System.Threading.Thread.CurrentThread.ManagedThreadId);

                Logger.LogToDisplay("Going to Sleep");

                System.Threading.Thread.Sleep(10000); ***//Hangs my Master Thread***
EventBroker.Execute("Topic2", null, EventArgs); //I want both of this to be asynchronous.

            }
}

所以,底线是我要找异步Eventbased发布/订阅的控制台应用程序......类似事件CAB罪SCSF和WPF中...

So bottom line is I am looking for Asynchronous Eventbased Publisher/Subscriber in Console application...similar to CAB event sin SCSF and in WPF...

感谢

推荐答案

这是很简单的事:

public class Foo
{
    public event Action MyEvent;

    public void FireEvent()
    {
        Action myevent = MyEvent;
        if (myevent != null)
        {
            Task.Factory.StartNew(() => myevent())
                .ContinueWith(t =>
                {
                    //TODO code to run in UI thread after event runs goes here
                }, CancellationToken.None
                , TaskContinuationOptions.None
                , TaskScheduler.FromCurrentSynchronizationContext());
        }
    }
}

如果您正在使用C#5.0,您可以使用等待这简化了这个code:

If you're using C# 5.0 you can use await which simplifies this code:

public class Foo
{
    public event Action MyEvent;

    public async Task FireEvent()
    {
        Action myevent = MyEvent;
        if (MyEvent != null)
        {
            await Task.Run(() => myevent());
            //TODO code to run in UI thread after event runs goes here
        }
    }
}

如果您不需要code在UI线程中运行启动后,事件处理程序全部建成,它可以代替保持在同一时间在UI线程上走,还可以简化code到刚:

If you don't need the code running in the UI thread to start after the event handlers are all completed, and it can instead keep going on the UI thread at the same time, you can also simplify the code to just:

public class Foo
{
    public event Action MyEvent;

    public void FireEvent()
    {
        Action myevent = MyEvent;
        if (MyEvent != null)
        {
            Task.Factory.StartNew(() => myevent());

            //TODO code to run in UI thread while event handlers run goes here
        }
    }
}

这篇关于在后台线程火灾事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆