0
votes

In my Windows Silverlight phone app, I click a button to scan a barcode and then scan the barcode sucesfuly, but whenever I press the button to scan again, it gives me a strange exception.

System.Reflection.TargetInvocationException was unhandled

Message: An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in System.Windows.ni.dll Additional information: Exception has been thrown by the target of an invocation.

I've searched a lot about it and have an idea that maybe its due to my Thread.Sleep code within that scan function.

How can I use Task.delay instead of Thread.sleep, and would that solve the problem? I think that it is a threading problem and I am not very good with multi-threading.

Here is my code:

 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 doesn't help.
            }
            MessageBox.Show("Scanned code : " + result.Text);
            result = null;
            MT = null;
            scanner = null;
            opts = null;
            check = false;
        }
        
        
    }

Note: even if I just click the scan button first time and open the scanner, and then press back without scanning anything, and then go back second time it produces exception.

So first time is fine no matter what, but so every second time entering scanner produce exception.

Reason for delay needed:

During scanning the library I am using (ZXing.Net.Mobile) doesn't auto focus itself, so until the barcode gets a scanned result, I have to initiate the auto focus manually, after every 2 seconds.

1
Why do want to have a delay at first place?Sparrow
Please see the edited post, Ive explained the reason of delay at the end. I would really appreciate if you could help me, I am trying to get out of this problem for weeks now. ThanksMuhammad Touseef
Did you try to Join that thread?VMAtm

1 Answers

1
votes

The exception sounds like either scanner.Autofocus or the Thread.Sleep throw an exception inside the thread which you don't handle.

To do this and use the more preferred Task.Delay you could rewrite your code as follows which also uses the more modern Task approach instead of directly working with 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);
 }

Additionally you could define the cts variable outside the event handler, allowing you to cancel the task when your form closes, etc. If the scanner.Scan method has an overload accepting a CancellationToken you should use this overload and provide it the ct cancellation token, so you could also cancel the scan task.