Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用asyc WAIT从事件更新UI_C#_Asynchronous_Async Await - Fatal编程技术网

C# 使用asyc WAIT从事件更新UI

C# 使用asyc WAIT从事件更新UI,c#,asynchronous,async-await,C#,Asynchronous,Async Await,我试图理解如何在使用异步/等待模式时从事件更新UI。 下面是我在WinForm应用程序上使用的测试代码。我甚至不确定这样做是否正确。允许pwe_StatusUpdate方法更新UI需要什么?此时会抛出跨线程操作错误 谢谢你的阅读 // calling code ProcessWithEvents pwe = new ProcessWithEvents(); pwe.StatusUpdate += pwe_StatusUpdate; await pwe.Run();

我试图理解如何在使用异步/等待模式时从事件更新UI。 下面是我在WinForm应用程序上使用的测试代码。我甚至不确定这样做是否正确。允许pwe_StatusUpdate方法更新UI需要什么?此时会抛出跨线程操作错误

谢谢你的阅读

 // calling code
    ProcessWithEvents pwe = new ProcessWithEvents();
    pwe.StatusUpdate += pwe_StatusUpdate;
    await pwe.Run();



 void pwe_StatusUpdate(string updateMsg)
    {
      // Error Here: Cross-thread operation not valid: Control '_listBox_Output' accessed from a thread other than the thread it was created on.
      _listBox_Output.Items.Add(updateMsg);
    }
-

//具有长时间运行的进程和事件的类
公共委托无效状态UpdateHandler(字符串updateMsg);
公共类ProcessWithEvents
{
公共事件状态更新处理程序状态更新;
公共异步任务运行()
{
等待任务。运行(()=>
{
对于(int i=0;i<10;i++)
{
RaiseUpdateEvent(String.Format(“Update{0}”,i));
睡眠(500);
}
});
}
私有void RaiseUpdateEvent(字符串消息)
{
如果(状态更新!=null)
状态更新(msg);
}
}

-

您应该使用
调用
控制方法
。它在控件的线程中执行一些代码。您还可以检查
invokererequired
属性,以检查是否需要调用
Invoke
方法(它检查调用方是否位于与创建控件的线程不同的线程上)

简单的例子:

void SomeAsyncMethod()
{
    // Do some work             

    if (this.InvokeRequired)
    {
        this.Invoke((MethodInvoker)(() =>
            {
                DoUpdateUI();

            }
        ));
    }
    else
    {
        DoUpdateUI();
    }
}

void DoUpdateUI()
{
    // Your UI update code here
}

在某些情况下,在调用
Invoke
方法之前,您应该检查
Control
IsHandleCreated
属性。如果
IsHandleCreated
返回false,则需要等待控件句柄的创建

//只需像这样声明一个委托即可

delegate void Add(string msg);
//然后声明委托方法,如下所示:

var add = new Add((msg) => {
   _listBox_Output.Items.Add(msg);
});
//现在只需给代表打电话:

void pwe_StatusUpdate(string updateMsg)
    {

      _listBox_Output.Invoke(add,updateMsg);
    }

简而言之,您的
async
方法可以采用
IProgress
,并且您的调用代码在该接口的实现中传递(通常是
Progress

public类ProcessWithUpdates
{
公共异步任务运行(IProgress进程)
{
等待任务。运行(()=>
{
对于(int i=0;i<10;i++)
{
如果(进度!=null)
进度报告(String.Format(“Update{0}”,i));
睡眠(500);
}
});
}
}
//呼叫码
ProcessWithUpdates pwp=新的ProcessWithUpdates();
等待pwp运行(新进度(pwp_状态更新));

这里是另一个例子

async void DoExport()
{
    var rMsg = "";
    var t = await Task<bool>.Factory.StartNew(() => ExportAsMonthReport(LastMonth.Name, LastYear.Name, out rMsg));

    if (t)
    {
          BeginInvoke((Action)(() =>
          {
               spinnerMain.Visible = false;
               menuItemMonth.Enabled = true;

               MetroMessageBox.Show(this, rMsg, "Export", MessageBoxButtons.OK, MessageBoxIcon.Information, 200);
          }));
   }
   else
   {
          BeginInvoke((Action)(() =>
          {
               spinnerMain.Visible = false;
               menuItemMonth.Enabled = true;

               MetroMessageBox.Show(this, rMsg, "Export", MessageBoxButtons.OK, MessageBoxIcon.Error, 200);
          }));
    }
}
async void DoExport()
{
var rMsg=“”;
var t=wait Task.Factory.StartNew(()=>ExportAsMonthReport(lastmount.Name,lastwear.Name,out rMsg));
if(t)
{
开始(动作)(()=>
{
spinnerMain.Visible=假;
menuItemMonth.Enabled=true;
MetroMessageBox.Show(这个,rMsg,“导出”,MessageBoxButtons.OK,MessageBoxIcon.Information,200);
}));
}
其他的
{
开始(动作)(()=>
{
spinnerMain.Visible=假;
menuItemMonth.Enabled=true;
显示(这个,rMsg,“导出”,MessageBoxButtons.OK,MessageBoxIcon.Error,200);
}));
}
}

这与进度建议一样有效。我正在使用这两种方法,非常感谢。在使用异步模式时,您不应该自己实现这一点<代码>进度
已在创建它的SynchronizationContext上执行。简单解决方案。很好用。
//调用代码
部分中的
ProcessWithProgress
应该是
ProcessWithUpdates
吗?
public class ProcessWithUpdates
{
  public async Task Run(IProgress<string> progress)
  {
    await Task.Run(() =>
    {
      for (int i = 0; i < 10; i++)
      {
        if (progress != null)
          progress.Report(String.Format("Update {0}", i));
        Thread.Sleep(500);
      }
    });
  }
}

// calling code
ProcessWithUpdates pwp = new ProcessWithUpdates();
await pwp.Run(new Progress<string>(pwp_StatusUpdate));
async void DoExport()
{
    var rMsg = "";
    var t = await Task<bool>.Factory.StartNew(() => ExportAsMonthReport(LastMonth.Name, LastYear.Name, out rMsg));

    if (t)
    {
          BeginInvoke((Action)(() =>
          {
               spinnerMain.Visible = false;
               menuItemMonth.Enabled = true;

               MetroMessageBox.Show(this, rMsg, "Export", MessageBoxButtons.OK, MessageBoxIcon.Information, 200);
          }));
   }
   else
   {
          BeginInvoke((Action)(() =>
          {
               spinnerMain.Visible = false;
               menuItemMonth.Enabled = true;

               MetroMessageBox.Show(this, rMsg, "Export", MessageBoxButtons.OK, MessageBoxIcon.Error, 200);
          }));
    }
}