简体   繁体   中英

Unable to get out of the async method in C#

I have a test as below. The below method calls the async method called " ReceiveC2dAsync ". This listens some to the message sent by " SendEventAsync " method. Before sending the message it starts listening.

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);
}

The method ReceiveC2dAsync looks as below. I want to get out of this method when the condition response.Count >= messageCount is satisfied. I will store the response in variable response and use it in the next subsequent steps.

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)
        {
        }
    }
}

Then the next method as below will be executed

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

But the problem currently is my execution did not come out of the ReceiveC2dAsync method even after the loop is ended. It just stays in that and times out stating Null Reference Exception. While debugging I got the required response. But since the execution did not proceed, and I am unable to proceed to next steps.

You must await your method async

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)
{
}

The async / await Pattern turns your code into a state machine using tasks. Since you do not use the await keyword, this code will "fire and forget". Your main thread will continue to run, ignoring the Thread of the async method, which is managed by the Task Scheduler.

Use the await keyword to continue with the thread as soon as the method state is complete.

When using await you need to change your method signature to async also.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM