简体   繁体   English

异步方法同步运行

[英]Async method runs synchronously

Where can I put my await keyword in this line of code that searches for a string in a textfile?在这行在文本文件中搜索字符串的代码中,我可以在哪里放置我的await关键字?

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())使方法同步(返回int而不是Task<int> )并使用Task.Run(() => CheckInLogs())在不同的任务中显式运行它

  • actually do some async work inside the method, ie using the ReadLineAsync method instead of ReadLine ( docs )实际上在方法内部做一些异步工作,即使用ReadLineAsync方法而不是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.关于使用 ReadLineAsync :即使使用ReadLineAsync并等待它会在不同的任务中执行该方法(即使其真正异步),您可能会发现调用线程最初仍被阻塞。

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 .这可能发生第一个await之前您执行一些需要一些时间才能完成的代码,并且由于尚未达到await ,它同步运行之前的代码。 In your code, the line var dataTable = ToDataTable(_manualReadTagList);在您的代码中,行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.您的代码正在同步运行,因为您的 CheckInLogs 方法没有使用 await 运算符。 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您的阅读是同步的,正如@SLaks 在评论中所说,我会使用 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 :)我确定您可以在代码中看到此消息:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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