当任务完成时运行一个函数

11

我希望能异步运行一个函数,以避免界面冻结。这是按钮点击事件:

private void btnEncrypt_Click(object sender, EventArgs e)
{
    // Create new Vigenere object instant
    cryptor = new Vigenere(txtPassword.Text, txtBox.Text);

    // Run encryption async
    Task<string> T = new Task<string>(cryptor.Encrypt);
    T.Start();
}

当任务 T 完成并返回其值时,我希望调用以下函数:

private void Callback(string return_value)
{
    txtBox.Text = return_value

    // Some other stuff here
}

如何实现这个目标?

你能使用 async 吗? - Alexei Levenkov
@AlexeiLevenkov 一个例子将会很有帮助。 - Xbyte Finance
http://blogs.msdn.com/b/csharpfaq/archive/2012/06/26/understanding-a-simple-async-program.aspx - Alexei Levenkov
3个回答

16
你可以使用ContinueWith(Action<Task>)方法来实现。因此,你可以像这样做:
```csharp task.ContinueWith(t => { // 在这里添加代码 }); ```
Task<string> t = new Task<string>(cryptor.Encrypt);
T.Start();

Task continuationTask = t.ContinueWith((encryptTask) => {
    txtBox.Text = encryptTask.Result;
    ...
})

实际上,这只是说在当前任务完成后执行该操作,完成可以是成功运行、失败或由于取消而提前退出。您可能希望进行一些错误处理,以确保您不会尝试使用已取消或出现故障的任务的结果。


2
但问题是,ContinueWith操作不会在主线程上执行,而是在我的情况下在工作线程中执行! - Mohit Atray

4
首先,在您的按钮点击事件中添加async。尝试使用以下代码:
private async void btnEncrypt_Click(object sender, EventArgs e)
{
     cryptor = new Vigenere(txtPassword.Text, txtBox.Text);
     await Task.Run(() => cryptor.Encrypt()).ContinueWith(result => { Callback(result.Result); });
}

1
您希望使用Task.Run并在其上等待。这将使方法在线程池线程上执行,并在完成后将返回的字符串分配给TextBox:
private async void btnEncrypt_Click(object sender, EventArgs e)
{
     cryptor = new Vigenere(txtPassword.Text, txtBox.Text);
     textBox.Text = await Task.Run(() => cryptor.Encrypt());
}

我觉得这很奇怪。Encrypt是做什么的? - Yuval Itzchakov
加密给定的文本 - Xbyte Finance
1
如果这会冻结用户界面,那么这似乎不是你实际的代码。请发布一个您问题的 [mcve]。 - Yuval Itzchakov
迭代用户输入的每个字符并对其进行加密...如果我用Thread.Sleep(10000)替换该代码,UI就不会冻结。 - Xbyte Finance

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接