0

我在 .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();
}
4

1 回答 1

2

如果我正确阅读了您的代码,则说明您处于危险的竞争状态。你有:

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. 这引发了另一个潜在问题:如果autoResetEventisnullUserID == null,则第二个WaitOne将抛出NullReferenceException。如果多个线程正在执行此代码,每个线程都会创建一个不同AutoResetEvent的别人的信号。

于 2013-04-11T18:33:10.133 回答