使用带参数的 C# 异步任务作为函数参数
Use C# async task with arguments as a function parameter
我正在构建自己的基于队列的系统,但到目前为止我遇到了一个小问题:如何将异步任务添加到另一个函数来处理它?
我的处理器函数是这样工作的:
我有一个队列对象:
public class Queue
{
public string Id;
public CancellationTokenSource Cts;
public Task Task;
public Queue(Task task, string id, CancellationTokenSource cts)
{
Id = id;
Cts = cts;
Task = task;
}}
以及将我的任务添加到 2 个列表的命令:List<Queue> ActiveQueues
和 List<Queue> Queued
ActiveQueues 是所有活动队列的列表,Queued 是所有队列的列表。
我的添加函数如下所示:
public async Task Add(Task task, string id, CancellationTokenSource cts)
{
var queue = new Queue(task, id, cts);
if (ActiveQueues.Count < MainWindow.appConfig.MaxAsyncSessions)
{
var exists = ActiveQueues.Find(q => q.Id == queue.Id);
if (exists == null) // I don't want 2 queues with the same id to run at once so I add it to the queued list that's processed by another function.
{
ActiveQueues.Add(queue);
ActiveQueueIds.Add(queue.Id);
await queue.Task;
}
else
{
Queued.Add(queue);
}
}
else
{
Queued.Add(queue);
}
}
问题是我的任务也有参数,所以像 queue.Add(AsyncFunction(param1, param2), "idExample", new CancellationTokenSource())
一样使用它会在将它添加到 ActiveQueues 列表之前触发函数。
做我现在想做的事情的正确方法是什么?
更改您的 Add
方法签名以接受委托:
public async Task Add(Func<Task> taskFactory, string id, CancellationTokenSource cts)
并相应地更改 Queue
ctor 并引入类似 Start
的方法,它将启动任务(基本上调用 taskFactory()
)并可选择验证它是否已经启动并缓存结果taskFactory()
或使用 Lasy<>
来处理它。
使用 Lazy
的简单实现如下所示(为简洁起见省略了一些代码):
class Queue
{
public Lazy<Task> Task;
public Queue(Func<Task> taskFactory)
{
Task = new Lazy<Task>(taskFactory);
}
}
// in your Add method:
var queue = new Queue(taskFactory);
await queue.Task.Value;
// Add call:
q.Add(() => AsyncFunction(param1, param2), "idExample", new CancellationTokenSource())
我正在构建自己的基于队列的系统,但到目前为止我遇到了一个小问题:如何将异步任务添加到另一个函数来处理它?
我的处理器函数是这样工作的:
我有一个队列对象:
public class Queue { public string Id; public CancellationTokenSource Cts; public Task Task; public Queue(Task task, string id, CancellationTokenSource cts) { Id = id; Cts = cts; Task = task; }}
以及将我的任务添加到 2 个列表的命令:List<Queue> ActiveQueues
和 List<Queue> Queued
ActiveQueues 是所有活动队列的列表,Queued 是所有队列的列表。
我的添加函数如下所示:
public async Task Add(Task task, string id, CancellationTokenSource cts)
{
var queue = new Queue(task, id, cts);
if (ActiveQueues.Count < MainWindow.appConfig.MaxAsyncSessions)
{
var exists = ActiveQueues.Find(q => q.Id == queue.Id);
if (exists == null) // I don't want 2 queues with the same id to run at once so I add it to the queued list that's processed by another function.
{
ActiveQueues.Add(queue);
ActiveQueueIds.Add(queue.Id);
await queue.Task;
}
else
{
Queued.Add(queue);
}
}
else
{
Queued.Add(queue);
}
}
问题是我的任务也有参数,所以像 queue.Add(AsyncFunction(param1, param2), "idExample", new CancellationTokenSource())
一样使用它会在将它添加到 ActiveQueues 列表之前触发函数。
做我现在想做的事情的正确方法是什么?
更改您的 Add
方法签名以接受委托:
public async Task Add(Func<Task> taskFactory, string id, CancellationTokenSource cts)
并相应地更改 Queue
ctor 并引入类似 Start
的方法,它将启动任务(基本上调用 taskFactory()
)并可选择验证它是否已经启动并缓存结果taskFactory()
或使用 Lasy<>
来处理它。
使用 Lazy
的简单实现如下所示(为简洁起见省略了一些代码):
class Queue
{
public Lazy<Task> Task;
public Queue(Func<Task> taskFactory)
{
Task = new Lazy<Task>(taskFactory);
}
}
// in your Add method:
var queue = new Queue(taskFactory);
await queue.Task.Value;
// Add call:
q.Add(() => AsyncFunction(param1, param2), "idExample", new CancellationTokenSource())