多次使用AutoResetEvent

本文关键字:AutoResetEvent | 更新日期: 2023-09-27 18:08:44

我在。net 4.0 c#应用程序中有两个异步调用一个web服务。这些是通过使用AutoResetEvent WaitOne()来控制的。

在我的本地机器上,这是按预期工作的。但是当我将它部署到服务器中时,在第一次调用中调用第二步的成功处理程序。

需要做什么改变才能使线程正常运行?

if (userID != null)
{
    AddressBookRequest req = new AddressBookRequest
    {
        contactsSearchCriteria = new ContactsSearchCriteria
        {
            searchUserID = userID.Trim()
        },
        HeaderParams = new HttpHeaderParms
        {
            UserId = userID.Trim(),
            UserPrincipalName = userID.Trim() ,
            ContentType = "application/xml"
        }
    };
    lookupServicesAssociate.SearchContactDetailsAsync(req);
    autoRestEvent = new AutoResetEvent(false);
    lookupServicesAssociate.SearchContactDetailsCompleted +=
        new EventHandler<ServiceResponseEventArgs<ContactDetailsPreview[]>>(AssociateSearchContactDetailsCompleted);
    autoRestEvent.WaitOne();
}
if (reportsToUserID != null)
{
    AddressBookRequest req1 = new AddressBookRequest
    {
        contactsSearchCriteria = new ContactsSearchCriteria
        {
            searchUserID = reportsToUserID.Trim()
        },
        HeaderParams = new HttpHeaderParms
        {
            UserId = reportsToUserID.Trim(),
            UserPrincipalName = reportsToUserID.Trim(), 
            ContentType = "application/xml"
        }
    };
    lookupServiceReports.SearchContactDetailsAsync(req1);
    lookupServiceReports.SearchContactDetailsCompleted +=
        new EventHandler<ServiceResponseEventArgs<ContactDetailsPreview[]>>(ReportsToAssociateSearchContactDetailsCompleted);
    autoRestEvent.WaitOne();
}

多次使用AutoResetEvent

如果我没看错你的代码,你有一个危险的竞争条件。你有:

lookupServicesAssociate.SearchContactDetailsAsync(req);
autoRestEvent = new AutoResetEvent(false);
lookupServicesAssociate.SearchContactDetailsCompleted +=
    new EventHandler<ServiceResponseEventArgs<ContactDetailsPreview[]>>(AssociateSearchContactDetailsCompleted);
autoRestEvent.WaitOne();

在第一行,调用async方法。然后,创建AutoResetEvent并分配事件处理程序。

如果SearchContactDetailsAsync在你分配回调之前完成,你的WaitOne将永远不会完成,因为回调不会被执行,事件永远不会被发出信号。

你真的应该写:

autoRestEvent = new AutoResetEvent(false);
lookupServicesAssociate.SearchContactDetailsCompleted +=
    new EventHandler<ServiceResponseEventArgs<ContactDetailsPreview[]>>(AssociateSearchContactDetailsCompleted);
lookupServicesAssociate.SearchContactDetailsAsync(req);
autoRestEvent.WaitOne();

虽然非常诚实,我想知道为什么你开始一个异步任务,然后只是等待它的完成。你在有效地同步地做这件事。

说了这么多,我不得不同意Pako的评论:除非UserID == null,否则这是不可能发生的。这引发了另一个潜在的问题:如果autoResetEventnullUserID == null,第二个WaitOne将抛出NullReferenceException。如果多个线程正在执行这段代码,每个线程都将创建一个不同的AutoResetEvent,这肯定会导致问题,因为您最终可能会等待一个永远不会发出信号的事件,或者等待错误的事件并捕获其他人的信号。