简体   繁体   中英

Async method runs synchronously

Where can I put my await keyword in this line of code that searches for a string in a textfile?

My application freezes when the search is on-going.

private async void BtnCheckLogs_OnClick(object sender, RoutedEventArgs e)
{
    _rowCount = await CheckInLogs();
    Header.Text = $@"Not found tag Count: {_rowCount}";
}
private async Task<int> CheckInLogs()
{
    IList<ManualReadTag> result = new List<ManualReadTag>();
    var notFoundTag = 0;
    if (_rowCount == 0)
    {
        MessageBox.Show("There are no tag to compare from the logs");
        return 0;
    }
    else
    {
        var dataTable = ToDataTable(_manualReadTagList);
        if (dataTable != null)
        {
            string[] lines = null;
            string currentAddress = null;
            foreach (DataRow row in dataTable.Rows)
            {
                var plaza = row[0].ToString();
                var lane = row[1].ToString();
                var tagNumber = row[3].ToString();
                var originalTrxnDtime = row[2];
                var trxnDtime = Convert.ToDateTime(row[2]).ToShortDateString();
                var year = trxnDtime.Split('/')[2];
                var month = trxnDtime.Split('/')[1].PadLeft(1,'0');
                var day = trxnDtime.Split('/')[0].PadLeft(1, '0'); ;

                var obj = JObject.Parse(json);
                var search = $@"{plaza}.Lanes.{lane}.Ip";
                var ipAddress = (string)obj.SelectToken(search);

               
                using (new ImpersonateUser("IETCADMIN", "", "M1nion$"))
                {
                    var dir = @"i\RFIDServiceLogs";
                    var fileName = $@"\\{ipAddress}\{dir}\{year}\{month}\{day}\RfidHandlerSystemLogs.txt";

                    var pattern = tagNumber;

                    var isFound = false;
                    try
                    {
                        using (var reader = new StreamReader(fileName))
                        {
                            string currentLine;
                            while ((currentLine = reader.ReadLine()) != null)
                            {
                                if (currentLine.Contains(tagNumber))
                                {
                                    isFound = true;
                                    break;
                                }
                            }
                        }

                        if (!isFound)
                        {
                            var mrt = new ManualReadTag
                            {
                                Plaza = Convert.ToInt16(plaza),
                                Lane = Convert.ToInt16(lane),
                                Tag_Number = tagNumber,
                                Trxn_DTime = Convert.ToDateTime(originalTrxnDtime)
                            };
                            result.Add(mrt);
                            notFoundTag++;
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                   
                }
            }

            ViewingGridFromComparison.ItemsSource = result;
        }
    }

    return notFoundTag;
}

The problem is that your async method is not actually doing any async work , and because of this it won't be executed asynchronously. A similar question was answered here .

If you want to force the execution to another task, you can invoke it like this:

_rowCount = await Task.Run(async () => await CheckInLogs());

This is a quick solution, but it may also solve other problems (more on this at the end).


Some other options would be to:

  • make the method synchronous (returning int instead of Task<int> ) and running it explicitly in a different task with Task.Run(() => CheckInLogs())

  • actually do some async work inside the method, ie using the ReadLineAsync method instead of ReadLine ( docs )


On using ReadLineAsync : even if using ReadLineAsync and awaiting it would execute the method in a different task (ie making it truly asynchronous), you may find that the calling thread is still initially blocked.

This can happen when before the first await you execute some code that takes some time to complete, and since the await has not been reached yet, the code before it runs synchronously . In your code, the line var dataTable = ToDataTable(_manualReadTagList); could be slow enough to cause this behaviour, but this depends on the actual implementation of this function.

In this case, it would make sense to invoke the method as

await Task.Run(async () => await CheckInLogs());

even if the method is actually doing some async work at some point , because it would force to run the method in a different task immediately.

Your code is running synchronously because your CheckInLogs method is not using an await operator. Your read is synchronous, and as @SLaks said on the comments, I would use ReadLineAsync: https://docs.microsoft.com/en-us/dotnet/api/system.io.streamreader.readlineasync?view=netframework-4.8

警告

I'm sure you can see this message on your code :)

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