c# - C#:后台任务中的耗时操作入队?
问题描述
我正在与一些后台进程作斗争。我的控制台应用程序中有两种方法。Aprivate static async Task<Dictionary<string, string>> GenerateSomething()
和另一种方法将某些内容发送到网络服务器。GenerateSomething-Method 比 Method 花费更多的时间private static async SendSomething()
。现在我有了在后台多次运行 GenerateSomething() 方法并用返回填充每个任务的队列的想法。
我已经开始编程,但我不知道如何在后台运行多个 GenerateSomething() 方法,而 SendSomething() 正在处理它自己。
这是我的最新结果:
class Program
{
private static Queue<Dictionary<string, string>> QueueOfDicts = new Queue<Dictionary<string, string>>();
private static int batchCount = 5000;
private static int queueMinThreshold = 10;
private static long genCounter = 0;
private static long dictCounter = 0;
private static Stopwatch stopwatch = new Stopwatch();
static void Main(string[] args)
{
GetSomething().Wait();
}
private static async Task<Dictionary<string, string>> GenerateSomething()
{
var Dict = new Dictionary<string, string>();
// Here I do some calculations which takes approximately 30 seconds
for (int i = 0; i < batchCount; i++)
{
// some calculations
}
dictCounter++;
Console.WriteLine($"Added Dict #{dictCounter} with {batchCount} to the Queue.");
return Dict;
}
private static async Task SendSomething()
{
long time = 0;
long avgTime = 0;
var counter = 0;
while (true)
{
try
{
var url = "https://.............";
var web = new Web(url);
var address = "xxxxxxxxxxx";
var service = new Service(web, address);
if (QueueOfDicts.Count > queueMinThreshold)
{
var result = QueueOfDicts.Dequeue();
Console.WriteLine("QueueCount: " + QueueOfDicts.Count);
try
{
stopwatch.Start();
// here i wait send the webresponse, which takes about 5 seconds
stopwatch.Stop();
time = stopwatch.ElapsedMilliseconds;
stopwatch.Reset();
}
catch (Exception ex)
{
await SendFailedMessage(ex);
GetSomething().Wait();
}
var index = 0;
foreach (var res in result)
{
//do something
index++;
}
genCounter += batchCount;
avgTime += time;
counter++;
if (counter >= 100000 / batchCount)
{
Console.WriteLine("Average " + avgTime / counter);
counter = 0;
avgTime = 0;
}
Console.WriteLine("{0} analyzes made -- LastCall: {1}ms", genCounter, time);
}
else
QueueOfDicts.Enqueue(await GenerateSomething());
}
catch (Exception ex)
{
Console.WriteLine("-----------ERROR----------: \n End with error: \n" + ex.ToString());
await SendFailedMessage(ex);
Console.WriteLine("Querytime:" + time);
Console.ReadLine();
}
}
}
private static async Task<Message> SendFailedMessage(Exception ex)
{
var Bot = new TelegramBotClient(".....");
return await Bot.SendTextMessageAsync("...", "Something went wrong: \n" + ex);
}
}
谁能帮助我,我如何private static async Task<Dictionary<string, string>> GenerateSomething()
在后台多次运行,同时private static async SendSomething()
做自己的工作?
希望你有足够的信息来帮助我。感谢所有可以帮助我完成这个小项目的人。
解决方案
为简单起见,我删除了与您的内部类有关的大部分代码。
目前在后台并行执行多个任务的最简单方法是使用 async-await 模式,即使用Tasks
. 下面你有一个这样的事情的最小例子,没有进入额外的细节,比如锁、线程安全等。
我建议对 C# 的任务并行库感兴趣,它会对你有很大帮助。
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
class Program
{
private static int batchCount = 5000;
private static int queueMinThreshold = 10;
static async Task Main(string[] args)
{
// Run 10 times
var arr = new Task<Dictionary<string, string>>[queueMinThreshold];
for (int i = 0; i < queueMinThreshold; i++)
{
int id = i;
arr[i] = Task.Run(async () => await GenerateSomething(id));
}
// Do whatever in the meantime
// Execute some other function call, like SendSomething()
// ...
// Finally await result of long-running operations (When all of them are finished)
await Task.WhenAll(arr);
// And, if needed, access those reults
var firstResult = arr[0].Result; // non-blocking call - it is already finished.
}
private static async Task<Dictionary<string, string>> GenerateSomething(int id)
{
var Dict = new Dictionary<string, string>();
// Here I do some calculations which takes approximately 30 seconds
for (int i = 0; i < batchCount; i++)
{
// some calculations
}
Console.WriteLine($"Added Dict #{id} with {batchCount} to the Queue.");
return Dict;
}
}