如何在下面的按钮中使用Thread

How to use Thread in the button below

当我按下按钮时,解码 Qrcode 效果很好,但我想用线程来完成。 我像下面这样写,但线程不起作用。 有谁知道,我该如何解决?
谢谢
这是我的代码:

private async void button2_Click(object sender, EventArgs e)
{
    await Task.Run(() =>
    {
        pictureBox1.Image = Image.FromFile(@"C:\Users....jpg");
        MessagingToolkit.QRCode.Codec.QRCodeDecoder decoder = new MessagingToolkit.QRCode.Codec.QRCodeDecoder();
        textBox2.Text = decoder.Decode(new QRCodeBitmapImage(pictureBox1.Image as Bitmap));
    });
}

这将使您的 UI 保持响应

private async void button2_Click(object sender, EventArgs e)
    {
        var Result = await Decode("Image Path");

        textBox2.Text = Result;
    }

    private async Task<string> Decode(string PathOfImage)
    {
        var DecodedText = string.Empty;
        var decoder = new MessagingToolkit.QRCode.Codec.QRCodeDecoder();

        await Task.Run(() =>
        {
            DecodedText = decoder.Decode(new QRCodeBitmapImage(Image.FromFile(PathOfImage) as Bitmap));
        });

        return DecodedText;
    }

更新 2:这是您可以在一个函数中完成的方法:

private async void button2_Click(object sender, EventArgs e)
    {
        var DecodedText = string.Empty;
        var decoder = new MessagingToolkit.QRCode.Codec.QRCodeDecoder();

        await Task.Run(() => {
            DecodedText = decoder.Decode(new QRCodeBitmapImage(Image.FromFile(PathOfImage) as Bitmap));
        });

        textBox2.Text = DecodedText;
    }

您应该在 Task 完成后更新 TextBox,此时您返回到 UI 线程。

private async void button2_Click(object sender, EventArgs e)
{
    var bitmap = await Task.Run(() =>
    {
        return (Bitmap)Image.FromFile(@"C:\Users....jpg");
    });
    pictureBox1.Image = bitmap;
    var result = await Task.Run(() =>
    {
        var decoder = new MessagingToolkit.QRCode.Codec.QRCodeDecoder();
        return decoder.Decode(new QRCodeBitmapImage(bitmap));
    });
    textBox2.Text = result;
}

更新: 更新 PictureBox 的代码也应该移出 Task.Run 正文。


更新:图片加载也会阻塞UI,所以我把它移到了一个单独的Task.

调度程序对象用于从线程或任务

修改UI

下面是如何使用任务

方法一

bool result ;
Task<bool> task = Task.Run<bool>(async () => await RefreshUIAsync());
str = task.Result;

public async Task<bool> RefreshUIAsync()
{
   bool result;
   result= await Task.Factory.StartNew(() => RefreshUI());
   return result;
}

private string RefreshUI()
{           
  bool result;
  try
  {
     this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
    {   
      string ImagePath="";
      pictureBox1.Image = Image.FromFile(ImagePath);
      .......
    });
    result=true;
  }
  catch (Exception ex)
  {
      result=false;
  }  
 return result;
}

方法二

RefreshUIAsync().Wait();  

public async Task RefreshUIAsync()
{
   await Task.Run(() => {
   This.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
    {   
      string ImagePath="";
      pictureBox1.Image = Image.FromFile(ImagePath);
      .......
    });
   });
}

下面是如何使用线程

方法一

myThread = new Thread(() => ThreaRefreshUI());
myThread.Start();

private void ThreaRefreshUI()
{

    try
    {
    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
    {   
      string ImagePath="";
      pictureBox1.Image = Image.FromFile(ImagePath);
      .......
    });
    }
    catch (Exception ex)
    {

    }
}

方法二

Thread thread = new Thread(new ThreadStart(ThreaRefreshUI));
thread.Start();

 public void ThreaRefreshUI()
 {
   try
   {
    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
    {   
      string ImagePath="";
      pictureBox1.Image = Image.FromFile(ImagePath);
      .......
    });
   }
   catch (Exception ex)
   {

   }
 }

方法三

 Thread thread = new Thread(ThreaRefreshUI);
 thread.Start();

 public void ThreaRefreshUI()
 {
   try
   {
    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
    {   
      string ImagePath="";
      pictureBox1.Image = Image.FromFile(ImagePath);
      .......
    });
   }
   catch (Exception ex)
   {

   }
 }