gpt4 book ai didi

c# - Async/Await 或 Task.Run 在控制台应用程序/Windows 服务中

转载 作者:太空狗 更新时间:2023-10-29 23:21:02 25 4
gpt4 key购买 nike

我一直在研究(包括查看关于该主题的所有其他 SO 帖子)实现(最有可能的)Windows 服务 worker 的最佳方法,该 worker 将从数据库中提取工作项并在“后台“即发即弃”方式(工作项管理将全部在异步方法中处理)。工作项将是 Web 服务调用和数据库查询。将对这些工作项的生产者应用一些限制,以确保采用某种衡量方法来安排工作。下面的示例非常基础,只是为了突出 while 循环和 for 循环的逻辑。哪个是理想的方法或者无关紧要?是否有更合适/更有效的方法来实现这一点?

异步/等待...

    private static int counter = 1;

static void Main(string[] args)
{
Console.Title = "Async";

Task.Run(() => AsyncMain());

Console.ReadLine();
}

private static async void AsyncMain()
{
while (true)
{
// Imagine calling a database to get some work items to do, in this case 5 dummy items
for (int i = 0; i < 5; i++)
{
var x = DoSomethingAsync(counter.ToString());

counter++;
Thread.Sleep(50);
}

Thread.Sleep(1000);
}
}

private static async Task<string> DoSomethingAsync(string jobNumber)
{
try
{
// Simulated mostly IO work - some could be long running
await Task.Delay(5000);
Console.WriteLine(jobNumber);
}
catch (Exception ex)
{
LogException(ex);
}

Log("job {0} has completed", jobNumber);

return "fire and forget so not really interested";
}

任务.运行...

    private static int counter = 1;

static void Main(string[] args)
{
Console.Title = "Task";

while (true)
{
// Imagine calling a database to get some work items to do, in this case 5 dummy items
for (int i = 0; i < 5; i++)
{
var x = Task.Run(() => { DoSomethingAsync(counter.ToString()); });

counter++;
Thread.Sleep(50);
}

Thread.Sleep(1000);
}
}

private static string DoSomethingAsync(string jobNumber)
{
try
{
// Simulated mostly IO work - some could be long running
Task.Delay(5000);
Console.WriteLine(jobNumber);
}
catch (Exception ex)
{
LogException(ex);
}

Log("job {0} has completed", jobNumber);

return "fire and forget so not really interested";
}

最佳答案

pull items of work from a database and process them in parallel asynchronously in a 'fire-and-forget' manner in the background

从技术上讲,您需要并发。您想要异步并发还是并行并发还有待观察...

The work items will be web service calls and database queries.

工作受 I/O 限制,因此这意味着异步并发是更自然的方法。

There will be some throttling applied to the producer of these work items to ensure some kind of measured approach to scheduling the work.

这里隐含了生产者/消费者队列的想法。这是一种选择。 TPL 数据流提供了一些不错的生产者/消费者队列,它们是异步兼容的并支持节流。

或者,您可以自己进行节流。对于异步代码,有一个名为 SemaphoreSlim 的内置节流机制。


TPL 数据流方法,带节流:

private static int counter = 1;

static void Main(string[] args)
{
Console.Title = "Async";
var x = Task.Run(() => MainAsync());
Console.ReadLine();
}

private static async Task MainAsync()
{
var blockOptions = new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 7
};
var block = new ActionBlock<string>(DoSomethingAsync, blockOptions);
while (true)
{
var dbData = await ...; // Imagine calling a database to get some work items to do, in this case 5 dummy items
for (int i = 0; i < 5; i++)
{
block.Post(counter.ToString());
counter++;
Thread.Sleep(50);
}
Thread.Sleep(1000);
}
}

private static async Task DoSomethingAsync(string jobNumber)
{
try
{
// Simulated mostly IO work - some could be long running
await Task.Delay(5000);
Console.WriteLine(jobNumber);
}
catch (Exception ex)
{
LogException(ex);
}
Log("job {0} has completed", jobNumber);
}

手动节流的异步并发方法:

private static int counter = 1;
private static SemaphoreSlim semaphore = new SemaphoreSlim(7);

static void Main(string[] args)
{
Console.Title = "Async";
var x = Task.Run(() => MainAsync());
Console.ReadLine();
}

private static async Task MainAsync()
{
while (true)
{
var dbData = await ...; // Imagine calling a database to get some work items to do, in this case 5 dummy items
for (int i = 0; i < 5; i++)
{
var x = DoSomethingAsync(counter.ToString());
counter++;
Thread.Sleep(50);
}
Thread.Sleep(1000);
}
}

private static async Task DoSomethingAsync(string jobNumber)
{
await semaphore.WaitAsync();
try
{
try
{
// Simulated mostly IO work - some could be long running
await Task.Delay(5000);
Console.WriteLine(jobNumber);
}
catch (Exception ex)
{
LogException(ex);
}
Log("job {0} has completed", jobNumber);
}
finally
{
semaphore.Release();
}
}

最后一点,我几乎不推荐 my own book在 SO 上,但我认为它真的会让你受益。特别是第 8.10 节(阻塞/异步队列)、11.5(限制)和 4.4(限制数据流 block )。

关于c# - Async/Await 或 Task.Run 在控制台应用程序/Windows 服务中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37169579/

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