如果异步引发,事件是否正常工作?
我有以下类的骨架。正如你可以在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线程上。
请注意,如果您异步提升事件并且处理程序需要更新用户界面,则需要与UI线程同步以更新任何用户控件。如果异步引发事件,则会对订阅事件的类承担更大的负担:他们必须知道如何执行UI线程同步。
对我来说,一般,我发现异步事件是不值得的麻烦,因为几乎总是我最终不得不处理UI程序中的这些事件。我得出的结论是,如果我希望事件异步处理,那么处理程序应该处理这个问题。
这不是一条硬性规定。不以任何方式。例如,默认情况下,System.Timers.Timer
会在ThreadPool线程上引发事件,但您可以指定SynchronizingObject
,以便它可以与UI线程同步。
如果您决定使用异步事件,那么我建议您包含一个工具,如Timer的SynchronizingObject
,这样UI客户端就可以使用您的类,而不必陷入UI线程同步的复杂性。
虽然我没有包含实现,但我认为你的第二个场景是适用的。基本上我将使用一个webrequest对象并异步调用它。它由第三方库处理,允许我按顺序编写调用,但它仍然在另一个线程上触发。你有关于如何使用调用将事件激发回UI线程的链接。 – deanvmc 2010-11-21 00:07:30
你可以通过“调用UI线程C#”进行谷歌搜索。这一个是非常简短的:http://blogs.msdn.com/b/csharpfaq/archive/2004/03/17/91685.aspx – Aliostad 2010-11-21 00:15:43
我在想这个:http://*.com/questions/1698889/raise-events-in-net-on-the-main-ui-thread,因为它看起来更有活力。 – deanvmc 2010-11-21 00:18:07