.NET:如何在 BeginInvoke 回调期间与表单对话?

标签 .net asynchronous delegates

我有一个长时间运行的函数¹:

public string FindPasswordFromHash(String hash)
{
    ...
}

它被称为:

private void Button1_Click(object sender, EventArgs e)
{
    PasswordTextBox.Text = FindPasswordFromHash(HashTextBox.Text);
}

现在我想将它转换成异步的 BeginInvoke/EndInvoke 委托(delegate)模式:

private void Button1_Click(object sender, EventArgs e)
{
   MyAsyncDelegate asyncDelegate = new MyAsyncDelegate(HashTextBox.Text);
   asyncDelegte.BeginInvoke(hash, CompleteCallback, null);
}

private void CompleteCallback(IAsyncResult ar)
{
   MyAsyncDelegate asyncDelegate = ((AsyncResult)ar).AsyncDelegate;
   PasswordTextBox.Text = asyncDelegate.EndInvoke(asyncResult);
}

delegate string MyAsyncDelegate(String hash);

当然这是行不通的,因为异步委托(delegate)的实现方式存在抽象漏洞:

"Cross-thread operation not valid: Control 'PasswordTextBox' accessed from a thread other than the thread it was created on."

鉴于发明异步委托(delegate)模式是为了将长时间运行的操作转换为异步操作 - 使用 BeginInvoke/EndInvoke 替代同步调用的正确技术是什么?

更具体地说,强制将回调编码回调用线程的方法是什么?


¹ 例如发明的函数名称

最佳答案

您正在正确处理 BeginInvoke() 和 EndInvoke() 调用。您只需要处理这样一个事实:操作 GUI 需要在 GUI 线程上完成。

幸运的是,框架提供了 Control.Invoke()方法,它允许您在 GUI 线程上执行代码。

我通常会这样做:

private void SetPasswordText(string password){
  if(InvokeRequired){
    MethodInvoker mi = () => SetPasswordText(password);
    Invoke(mi);
    return;
  }
  PasswordTextBox.Text = password;
}

对于这种特殊情况,您也可以这样做

private void RecoveryCompleteCallback(IAsyncResult ar)
{
   MyAsyncDelegate asyncDelegate = ((AsyncResult)ar).AsyncDelegate;
   string password = asyncDelegate.EndInvoke(asyncResult);
   Invoke(()=>{PasswordTextBox.Text = password;});
}

如果你使用 C# 2.0,你会这样做:

MethodInvoker mi = delegate(){ SetPasswordText(password); };
Invoke(mi);

Invoke(delegate(){PasswordTextBox.Text = password;});

关于.NET:如何在 BeginInvoke 回调期间与表单对话?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/508386/

相关文章:

c# - 在 Windows.Forms 应用程序中使用 Wea​​kEventManager

javascript - Node.js 使用 Series 函数(模式?)实现流控制的意外结果

ios - 自定义委托(delegate)没有被调用

c# - Observable.FromEvent 和 CreateDelegate 参数映射

javascript - 为什么我的异步函数不与回调结合产生结果?

c# - 为什么 lambda 表达式不是 "interned"?

c# - 将 KeyValuePair<int,string> 转换为 int[] 数组和 string[] 数组

.net - Visual Studio 和项目引用路径的最大长度

c# - 使用 lambda 表达式与私有(private)方法

javascript - 如何等待一组异步回调函数?