如何在Windows Silverlight应用程序中使用任务延迟而不是线程睡眠

时间:2017-03-04 14:51:54

标签: c# multithreading windows-phone-8 task-parallel-library barcode-scanner

在我的windows silverlight手机应用程序中,我点击一个按钮扫描条形码然后扫描条形码sucesfuly,但每当我按下按钮再次扫描时,它给了我一个奇怪的例外。

System.Reflection.TargetInvocationException was unhandled

消息:类型为' System.Reflection.TargetInvocationException'的未处理异常发生在System.Windows.ni.dll中 附加信息:调用目标引发了异常。

  

我已经搜索了很多关于它并且有一个想法可能是由于我的Thread.Sleep代码在该扫描功能中。

     

我将把我的代码放在下面,请建议我如何使用Task.delay而不是Thread.sleep,这也可以解决问题?我认为这是一个线程问题,我对多线程不是很好,所以请帮助

这是我的代码

 private async void ScanClick(object sender, EventArgs e)
    {

        var scanner = new MobileBarcodeScanner();
        var check = true;
        var opts = new MobileBarcodeScanningOptions();
        opts.PossibleFormats = new List<BarcodeFormat>
        {
            BarcodeFormat.EAN_8,
            BarcodeFormat.EAN_13
        };
        Thread MT = new Thread(new ThreadStart(delegate
        {
            while (check)
            {
                scanner.AutoFocus();
                Thread.Sleep(autoFocusInterval);//value of autoFocus is 2000
            }
        }));
        MT.Start();

        var result = await scanner.Scan(opts);
        if(result!=null)
        {
            if(MT.IsAlive)
            {
                MT.Abort();//I try to abort to prevent the error, but it doesnt help.
            }
            MessageBox.Show("Scanned code : " + result.Text);
            result = null;
            MT = null;
            scanner = null;
            opts = null;
            check = false;
        }


    }

注意即使我只是第一次点击扫描按钮并打开扫描仪,然后按下而不扫描任何内容,然后第二次返回它会产生异常。

  

所以无论如何第一次都很好,但所以每次进入扫描仪都会产生异常。

**需要延迟的原因:** 在扫描我正在使用的库(ZXing.Net.Mobile)时,它不会自动对焦,所以在条形码获得扫描结果之前,我必须在每2秒后手动启动自动对焦。

提前致谢

1 个答案:

答案 0 :(得分:1)

异常听起来像是scanner.Autofocus或Thread.Sleep在您不处理的线程内抛出异常。

要执行此操作并使用更优选的Task.Delay,您可以按如下方式重写代码,这也使用更现代的Task方法,而不是直接使用Threads:

var cts = new CancellationTokenSource();
var ct = cts.Token;
var mtTask = Task.Run(async () =>
{
  while (true) // Loop will be exited when cts.Cancel is called as Task.Delay will respond with an OperationCancelledException
  {
    scanner.AutoFocus();
    await Task.Delay(autoFocusInterval, ct);
   }
 }, ct);

 var result = await scanner.Scan(opts);
 cts.Cancel();
 try
 {
   await mtTask;
 }
 catch (OperationCancelledException)
 {}
 if (result != null)
 {
   MessageBox.Show("Scanned code : " + result.Text);
 }

此外,你可以在事件处理程序之外定义cts变量,允许你在表单关闭时取消任务等。如果scanner.S.Save方法有一个接受CancellationToken的重载你应该使用这个重载并提供它ct取消令牌,因此您也可以取消扫描任务。