如果异步引发,事件是否正常工作?

问题描述:

我有以下类的骨架。正如你可以在TODO中看到的:评论我将在这里实现一个AsyncEnumerator结构。此方法将抓取请求并将数据传递给另一个要处理的方法。基于这个过程,我想调用事件,SendMilestoneReached或SendFailed。我担心这些可能发生在AsyncEnumerator的另一个线程上。如果异步引发,事件是否正常工作?

这是否会影响将调用Webtext类的UI线程?

/// <summary> 
/// Sends Webtexts. 
/// </summary> 
public class Webtext 
{ 
    #region Event Definitions 

    // Events. 
    public event EventHandler<SendingEventArgs> SendStarted = delegate { }; 
    public event EventHandler<SendingEventArgs> SendFailed = delegate { }; 
    public event EventHandler<SendingEventArgs> SendSuccessful = delegate { }; 
    public event EventHandler<SendingEventArgs> SendMilestoneReached = delegate { }; 

    // Shared EventArgs Object, Consumed by the Events. 
    SendingEventArgs EventArgs = new SendingEventArgs(); 

    #endregion 

    /// <summary> 
    /// Executes the send request. 
    /// </summary> 
    /// <param name="Operator">The operator whos service to use.</param> 
    /// <param name="Username">The username of the requested operator.</param> 
    /// <param name="Password">The password of the requested operator.</param> 
    /// <param name="Content">The content to send.</param> 
    /// <param name="Recipient">The recipient to recieve the content.</param> 
    public void ExecuteSendRequest(string Operator, 
            string Username, 
            string Password, 
            string Content, 
            string Recipient) 
    { 
     //TODO: Implement Async requests here. 
    } 

    #region Event Handlers 

    /// <summary> 
    /// Called when [sending started]. 
    /// </summary> 
    protected void OnSendingStarted() 
    { 
     SendStarted(this, EventArgs); 
    } 

    /// <summary> 
    /// Called when [send fail]. 
    /// </summary> 
    protected void OnSendFail() 
    { 
     SendFailed(this, EventArgs); 
    } 

    /// <summary> 
    /// Called when [send successful]. 
    /// </summary> 
    protected void OnSendSuccessful() 
    { 

     SendSuccessful(this, EventArgs); 
    } 

    /// <summary> 
    /// Called when [send milestone reached]. 
    /// </summary> 
    protected void OnSendMilestoneReached() 
    { 
     SendMilestoneReached(this, EventArgs); 
    } 

    #endregion 


} 

事件由相同的Thread创建,它引发了它。这个原理听起来很简单,但很重要。

所以:

方案1应用程序打开。 Webtext由UI线程中的表单初始化,并且它的发送被调用。 Webtext同步发送请求并引发事件。在整个过程中,所有操作都在UI线程上完成。

场景2应用程序已打开。 Webtext由UI线程中的表单初始化,并且它的发送被调用。 Webtext使用工作线程异步地发送请求。第二个线程在完成时触发事件。这将是工作者线程(后台或前台,取决于您如何创建线程)。通过此线程调用UI元素的任何调用都需要使用Invoke完成。

正如你所看到的,它非常依赖于你如何实现发送方法。我看不到任何发送自己的实现,所以我只能说如果你产生一个线程或使用线程池它将在工作线程上,否则简单地同步发送将在UI线程上。

+0

虽然我没有包含实现,但我认为你的第二个场景是适用的。基本上我将使用一个webrequest对象并异步调用它。它由第三方库处理,允许我按顺序编写调用,但它仍然在另一个线程上触发。你有关于如何使用调用将事件激发回UI线程的链接。 – deanvmc 2010-11-21 00:07:30

+0

你可以通过“调用UI线程C#”进行谷歌搜索。这一个是非常简短的:http://blogs.msdn.com/b/csharpfaq/archive/2004/03/17/91685.aspx – Aliostad 2010-11-21 00:15:43

+0

我在想这个:http://*.com/questions/1698889/raise-events-in-net-on-the-main-ui-thread,因为它看起来更有活力。 – deanvmc 2010-11-21 00:18:07

请注意,如果您异步提升事件并且处理程序需要更新用户界面,则需要与UI线程同步以更新任何用户控件。如果异步引发事件,则会对订阅事件的类承担更大的负担:他们必须知道如何执行UI线程同步。

对我来说,一般,我发现异步事件是不值得的麻烦,因为几乎总是我最终不得不处理UI程序中的这些事件。我得出的结论是,如果我希望事件异步处理,那么处理程序应该处理这个问题。

这不是一条硬性规定。不以任何方式。例如,默认情况下,System.Timers.Timer会在ThreadPool线程上引发事件,但您可以指定SynchronizingObject,以便它可以与UI线程同步。

如果您决定使用异步事件,那么我建议您包含一个工具,如Timer的SynchronizingObject,这样UI客户端就可以使用您的类,而不必陷入UI线程同步的复杂性。

+0

我没有选择,我正在使用WP7,所以我的应用程序需要的大部分调用都是异步的。 – deanvmc 2010-11-21 00:43:12

+0

我将如何去同步我刚刚要使用的线程。 Dispatcher.BeginInvoke(()=> {此代码在UI线程上 });由于在我上面的链接很多花式选项不会使用wp7 – deanvmc 2010-11-21 00:46:23