【问题标题】:Async method runs synchronouslyAsync 方法同步运行
【发布时间】:2021-07-17 01:19:54
【问题描述】:

我在哪里可以将我的await 关键字放在这行搜索文本文件中的字符串的代码中?

当搜索正在进行时,我的应用程序会冻结。

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

【问题讨论】:

标签: c#


【解决方案1】:

问题在于你的异步方法实际上并没有做任何异步工作,因此它不会被异步执行。 here回答了类似的问题。

如果你想强制执行另一个任务,你可以这样调用它:

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

这是一个快速的解决方案,但它也可以解决其他问题(最后会详细介绍)。


其他一些选择是:

  • 使方法同步(返回 int 而不是 Task&lt;int&gt;)并使用 Task.Run(() =&gt; CheckInLogs()) 在不同的任务中显式运行它

  • 实际上在方法内部做一些异步工作,即使用ReadLineAsync方法而不是ReadLine (docs)


关于使用 ReadLineAsync:即使使用 ReadLineAsync 并等待它会在不同的任务中执行该方法(即使其真正异步),您可能发现调用线程最初还是被阻塞的。

这可能发生在第一个await 之前执行一些需要一些时间才能完成的代码,并且由于尚未达到await,因此它运行之前的代码同步。 在您的代码中,var dataTable = ToDataTable(_manualReadTagList); 行可能会慢到足以导致此行为,但这取决于此函数的实际实现。

在这种情况下,调用该方法是有意义的

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

即使该方法实际上在某个时间点做了一些异步工作,因为它会强制在不同的任务中立即运行该方法。

【讨论】:

  • 如果 CheckInLogs 是一个真正的异步方法就可以了,但是等待一个同步方法没有意义。
  • 由于某种原因,ReadLineAsync 对我不起作用。我刚刚使用了 Task.Run() ..... 用于 ui 的 this.Dispatcher
  • @Kaitiff 使用ReadLineAsync 方法查看我关于“仅”的编辑。
【解决方案2】:

您的代码正在同步运行,因为您的 CheckInLogs 方法未使用 await 运算符。 您的阅读是同步的,正如@SLaks 在 cmets 上所说,我会使用 ReadLineAsync:https://docs.microsoft.com/en-us/dotnet/api/system.io.streamreader.readlineasync?view=netframework-4.8

我确定您可以在您的代码中看到此消息 :)

【讨论】:

  • 该消息看起来像是来自 ReSharper 的提示
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多