gpt4 book ai didi

c# - 动态链接 `Task` 且不阻塞线程

转载 作者:太空宇宙 更新时间:2023-11-03 18:25:11 25 4
gpt4 key购买 nike

我正在尝试链接 Task<T> C# 中的对象与在 JavaScript 中完成的一样,并且不会阻塞 UI 线程。

我看到有一个类似的问题here , 但它使用非通用 Task对象作为流程函数的返回类型。我尝试对 Task<T> 做同样的事情.

我也看到了 here是一个更接近我需要的问题,但接受的答案似乎使用 .Result两次,我猜这会阻塞 UI 线程。另外请注意,我是动态链接任务的,所以我无法遵循一些简单的解决方法。还有,Then给出的实现 here似乎也是同步的(我不确定简单地更改这个旧示例代码上的 TaskContinuationOptions 是否会达到我想要的效果)。

这是我现在拥有的,但我什至无法在不阻塞线程的情况下编译它:

    // Initial dummy task.
private Task<bool> taskChain = Task.Factory.StartNew<bool>(() => true);

// Chain dynamically on button click.
private async void DoSth_Click(object sender, RoutedEventArgs e)
{
var data = ....;
System.Threading.Tasks.Task<bool> del = async (t) => { return await ConvertAsync(data); };
taskChain = taskChain.ContinueWith<bool>(() => del);
var res = await taskChain;
}

我尝试了各种不同的方法,但我不知道如何才能转 Task<T>Func<Task<T>, T>ContinueWith<bool>()似乎需要(至少没有做一些讨厌的 UI 线程阻塞操作)。

我希望这很容易,但我不太明白这里的解决方案...难道没有一个简单易行的好方法吗?

(注意:我想我可能应该在 Unwrap() 之后调用 ContinueWith(),但此时这似乎是一个细节...)

最佳答案

UnWrap 是你的 friend 。它将允许您有一个解析为 Task 的延续方法,然后在延续甚至触发之前获得表示该任务的 Task

另请注意,FromResult 应用于创建已完成的任务。

private Task<bool> taskChain = Task.FromResult(true);
private async void DoSth_Click(object sender, RoutedEventArgs e)
{
var data = CreateData();
taskChain = taskChain.ContinueWith(t => ConvertAsync(data))
.Unwrap();
var res = await taskChain;
}

请注意,我建议不要在点击处理程序中在线执行此操作。创建一个能够对任务进行排队的类,然后使用那个。当然,这样的队列类只是遵循相同的模式:

public class TaskQueue
{
private Task previous = Task.FromResult(false);
private object key = new object();

public Task<T> Enqueue<T>(Func<Task<T>> taskGenerator)
{
lock (key)
{
var next = previous.ContinueWith(t => taskGenerator()).Unwrap();
previous = next;
return next;
}
}
public Task Enqueue(Func<Task> taskGenerator)
{
lock (key)
{
var next = previous.ContinueWith(t => taskGenerator()).Unwrap();
previous = next;
return next;
}
}
}

这将允许你写:

private TaskQueue taskQueue = new TaskQueue();
private async void DoSth_Click(object sender, RoutedEventArgs e)
{
var data = CreateData();
var res = await TaskQueue.Enqueue(ConvertAsync(data));
}

现在,您的任务排队机制已与此点击处理程序需要执行的业务逻辑分离。

关于c# - 动态链接 `Task<T>` 且不阻塞线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36021645/

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