gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 01:48:19 35 4
gpt4 key购买 nike

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

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/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com