【问题标题】:Await Action() is not awaited不等待 Await Action()
【发布时间】:2020-02-04 14:10:22
【问题描述】:

我正在使用 ZXing.Net.Mobile 库来扫描二维码。我想将负责扫描的代码放在单独的类中,这样我就可以从中调用一个方法,它会返回结果。类似的东西:

var scanner = new ZXing.Mobile.MobileBarcodeScanner();

var result = await scanner.Scan();

if (result != null)
    Console.WriteLine("Scanned Barcode: " + result.Text);

这是来自官方存储库的示例,但它不起作用(至少对我而言)。 所以我创建了一个类,并将 DID 工作的代码放在其他地方。这是课程代码:

public class QrHandler 
{
    public ZXingScannerPage scanPage { get; set; }
    public string Result { get; set; }
    public async Task<string> Scan()
    {
        var options = new ZXing.Mobile.MobileBarcodeScanningOptions
        {
            PossibleFormats = new List<ZXing.BarcodeFormat>
            {
                ZXing.BarcodeFormat.QR_CODE
            },
            TryHarder = false,
            AutoRotate = false,
            TryInverted = false,
        };

        scanPage = new ZXingScannerPage();
        scanPage.AutoFocus();

        scanPage.OnScanResult += (result) =>
        {
            scanPage.IsScanning = false;

            Device.BeginInvokeOnMainThread(async () =>
            {
                Application.Current.MainPage.Navigation.PopAsync();
                try
                {
                    Result = result.Text;    
                }
                catch (Exception ex)
                {
                    Result = ex.Message;
                }
            });
        };

        await Application.Current.MainPage.Navigation.PushAsync(scanPage);
        return Result;
    }
}

我通过如下方法调用它:

public async Task<string> Validate()
{
    string _Result = "OK";
    QrHandler q = new QrHandler();
    _Result = await q.Scan();
    return _Result;
}

问题是 Validate() 在 q.Scan() 返回任何值之前返回 _Result。 q.Scan() 完成后不应该触发吗?

【问题讨论】:

  • Device.BeginInvokeOnMainThread 接受Action&lt;T&gt;,它不允许指定任何返回类型,并且由于只能等待返回TaskTask&lt;T&gt; 的方法,因此您的异步lambda 将同步运行.

标签: c# xamarin.forms zxing.net


【解决方案1】:

OnScanResult 事件处理程序执行之前,您不能从Scan() 返回。

目前尚不清楚何时引发此事件,但如果它确实在您预期的时候引发,您可以在 Scan() 方法中使用 SemaphoreSlim 异步阻止:

public async Task<string> Scan()
{
    var options = new ZXing.Mobile.MobileBarcodeScanningOptions
    {
        PossibleFormats = new List<ZXing.BarcodeFormat>
        {
            ZXing.BarcodeFormat.QR_CODE
        },
        TryHarder = false,
        AutoRotate = false,
        TryInverted = false,
    };

    scanPage = new ZXingScannerPage();
    scanPage.AutoFocus();

    using (SemaphoreSlim semaphoreSlim = new SemaphoreSlim(0, 1))
    {
        scanPage.OnScanResult += (result) =>
        {
            scanPage.IsScanning = false;

            Device.InvokeOnMainThread(async () =>
            {
                await Application.Current.MainPage.Navigation.PopAsync();
                try
                {
                    Result = result.Text;
                }
                catch (Exception ex)
                {
                    Result = ex.Message;
                }
                semaphore.Release();
            });
        };

        await Application.Current.MainPage.Navigation.PushAsync(scanPage);
        await semaphoreSlim.WaitAsync();
    }

    return Result;
}

【讨论】:

  • 它有效,谢谢!不过,我将不得不阅读 SemaphoreSlim 以了解它为什么起作用:)
  • 小问题。我忽略了您已将 BeginInvokeOnMainThread 更改为 InvokeOnMainThread 并使用 Begin.. 运行它。不过,它确实有效。为什么要为 Invoke.. 更改它?
  • @robs23:等待委托被执行。我意识到你仍然不能退出该方法,直到它退出。
猜你喜欢
  • 1970-01-01
  • 2017-10-15
  • 2015-06-29
  • 1970-01-01
  • 2021-08-03
  • 2021-12-11
  • 2016-03-08
  • 1970-01-01
  • 2020-07-23
相关资源
最近更新 更多