无法摆脱C#中的异步方法

时间:2018-08-13 13:11:51

标签: c# asynchronous

我进行了如下测试。下面的方法调用名为“ ReceiveC2dAsync ”的异步方法。这将侦听“ SendEventAsync ”方法发送的消息。在发送消息之前,它开始监听。

public void CreatePlatformEventForDeviceCreatedWithoutObjectId()
{
    var corId = Guid.NewGuid().ToString();
    ScenarioContext.Current["CorrelationId"] = corId;
    var iotHubUri = this.objStartupFixture.IoTHubHostName;
    var deviceName = this.objStartupFixture.DevicePEName;
    var iotHubConnxnString = this.objStartupFixture.IoTHubConnectionString;
    this.ReceiveC2dAsync(iotHubUri, deviceName, iotHubConnxnString, 2);          
    var jsonContent = ScenarioContext.Current["InstanceObj"] as JObject;
    Microsoft.Azure.Devices.Client.Message msg = this.CreateMessageForD2C(jsonContent, true);
    msg.CorrelationId = corId;
    this.deviceClient.SendEventAsync(msg);
    Thread.Sleep(2000);
}

方法 ReceiveC2dAsync 如下所示。当满足条件 response.Count> = messageCount 时,我想退出此方法。我会将响应存储在变量 response 中,并在随后的后续步骤中使用它。

private async void ReceiveC2dAsync(string iotHubUri, string deviceName, string iotHubConnxnString, int messageCount)
{
    var deviceId = this.GetDeviceID(iotHubConnxnString, deviceName);
    this.deviceClient = DeviceClient.Create(iotHubUri, new DeviceAuthenticationWithRegistrySymmetricKey(deviceName, deviceId), Microsoft.Azure.Devices.Client.TransportType.Amqp_Tcp_Only);
    var correlationId = ScenarioContext.Current["CorrelationId"] as string;
    var dataRxd = false;
    var flag = true;
    ScenarioContext.Current["DataRxdStatus"] = dataRxd;
    var response = new List<string>();
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    while (flag)
    {
        try
        {
            if (stopwatch.ElapsedMilliseconds > 30000)
            {
                throw new Exception("Time elapsed waiting for C2D message");
            }
            Microsoft.Azure.Devices.Client.Message receivedMessage = await this.deviceClient.ReceiveAsync();
            if (receivedMessage.CorrelationId.ToString() != correlationId)
            {
                if (stopwatch.ElapsedMilliseconds > 30000)
                {
                    throw new Exception("Time elapsed waiting for C2D message");
                }

                continue;
            }

            var eventType = receivedMessage.Properties["eventType"];
            response.Add(Encoding.ASCII.GetString(receivedMessage.GetBytes()));
            ScenarioContext.Current["C2DResponse"] = response;
            if (response.Count >= messageCount)
            {
                flag = false;
                dataRxd = true;
                ScenarioContext.Current["DataRxdStatus"] = dataRxd;
                stopwatch.Stop();
                break;
            }
        }
        catch (ObjectDisposedException)
        {
        }
    }
}

然后将执行下面的下一个方法

public void CheckDeviceInstanceAndRelatedConfigurationInstance()
{
    \\This response I will receive from the above async method.
    var c2dResponse = ScenarioContext.Current["C2DResponse"] as List<string>; 
}

但是当前的问题是即使循环结束后,我的执行也没有从 ReceiveC2dAsync 方法中执行。它只是停留在那,并且超时,说明为Null Reference Exception。在调试时,我得到了所需的响应。但是由于执行没有进行,所以我无法继续执行下一步。

2 个答案:

答案 0 :(得分:0)

您必须await异步使用方法

public async Task CreatePlatformEventForDeviceCreatedWithoutObjectId()
{
    //your code
    await this.ReceiveC2dAsync(iotHubUri, deviceName, iotHubConnxnString, 2);          
    //your code
}

private async Task ReceiveC2dAsync(string iotHubUri, string deviceName, string iotHubConnxnString, int messageCount)
{
}

答案 1 :(得分:0)

异步/等待模式使用任务将代码转变为状态机。由于您不使用await关键字,因此此代码将“触发并忘记”。您的主线程将继续运行,忽略由Task Scheduler管理的async方法的Thread。

方法状态完成后,请使用await关键字继续执行线程。

使用await时,您还需要将方法签名也更改为异步。