2010-11-20 22 views
2

我有以下類的骨架。正如你可以在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 


} 

回答

3

事件由相同的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://stackoverflow.com/questions/1698889/raise-events-in-net-on-the-main-ui-thread,因爲它看起來更有活力。 – deanvmc 2010-11-21 00:18:07

3

請注意,如果您異步提升事件並且處理程序需要更新用戶界面,則需要與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