我有一个Windows服务,根据计划运行各种作业.确定要运行的作业后,会将一个计划对象列表发送到迭代列表并运行每个作业的方法.问题是由于外部数据库调用,某些作业最多可能需要10分钟才能运行.
我的目标是没有一个工作阻止其他队列,基本上一次有多个运行.我认为使用async和await可以解决这个问题,但我以前从未使用过这些.
现行代码:
public static bool Load(List<Schedule> scheduleList)
{
foreach (Schedule schedule in scheduleList)
{
Load(schedule.ScheduleId);
}
return true;
}
public static bool Load(int scheduleId)
{
// make database and other external resource calls
// some jobs run for up to 10 minutes
return true;
}
Run Code Online (Sandbox Code Playgroud)
我尝试更新到这段代码:
public async static Task<bool> LoadAsync(List<Schedule> scheduleList)
{
foreach (Schedule schedule in scheduleList)
{
bool result = await LoadAsync((int)schedule.JobId, schedule.ScheduleId);
}
return true;
}
public async static Task<bool> LoadAsync(int scheduleId)
{
// make database …
Run Code Online (Sandbox Code Playgroud) 我将如何构造下面的代码,以便调用异步方法?
Parallel.For(0, elevations.Count(), delegate(int i)
{
allSheets.AddRange(await BuildSheetsAsync(userID, elevations[i], includeLabels));
});
Run Code Online (Sandbox Code Playgroud) 我有一个异步方法,GetExpensiveThing()
它执行一些昂贵的I/O工作.这就是我使用它的方式:
// Serial execution
public async Task<List<Thing>> GetThings()
{
var first = await GetExpensiveThing();
var second = await GetExpensiveThing();
return new List<Thing>() { first, second };
}
Run Code Online (Sandbox Code Playgroud)
但由于这是一种昂贵的方法,我想并行执行这些调用.我本以为移动等待会解决这个问题:
// Serial execution
public async Task<List<Thing>> GetThings()
{
var first = GetExpensiveThing();
var second = GetExpensiveThing();
return new List<Thing>() { await first, await second };
}
Run Code Online (Sandbox Code Playgroud)
这不起作用,所以我将它们包装在一些任务中,这有效:
// Parallel execution
public async Task<List<Thing>> GetThings()
{
var first = Task.Run(() =>
{
return GetExpensiveThing();
});
var second = Task.Run(() =>
{ …
Run Code Online (Sandbox Code Playgroud) 我正在查看异步的某个示例代码,并注意到它实现方式的一些问题.在查看代码时,我想知道使用并行循环遍历列表是否更有效,而不是正常循环遍历列表.
据我所知,性能差异很小,两者都占用了每个处理器,两者都在相同的时间内完成.
这是第一种方式
var tasks= Client.GetClients().Select(async p => await p.Initialize());
Run Code Online (Sandbox Code Playgroud)
这是第二个
var tasks = Client.GetClients().AsParallel().Select(async p => await p.Initialize());
Run Code Online (Sandbox Code Playgroud)
假设两者之间没有区别,我是否正确?
完整的程序可以在下面找到
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
RunCode1();
Console.WriteLine("Here");
Console.ReadLine();
RunCode2();
Console.WriteLine("Here");
Console.ReadLine();
}
private async static void RunCode1()
{
Stopwatch myStopWatch = new Stopwatch();
myStopWatch.Start();
var tasks= Client.GetClients().Select(async p => await p.Initialize());
Task.WaitAll(tasks.ToArray());
Console.WriteLine("Time ellapsed(ms): " + myStopWatch.ElapsedMilliseconds);
myStopWatch.Stop();
}
private async …
Run Code Online (Sandbox Code Playgroud) 等待故障任务(具有异常集的任务)时,await
将重新抛出存储的异常.如果存储的异常是a AggregateException
,它将重新抛出第一个并丢弃其余的异常.
我们如何使用await
并同时抛出原件AggregateException
以便我们不会意外丢失错误信息?
注意,当然可以考虑使用hacky解决方案(例如,试一试await
,然后调用Task.Wait
).我真的希望找到一个干净的解决方案.这里最好的做法是什么?
我想过使用自定义awaiter,但内置TaskAwaiter
包含很多魔法,我不知道如何完全重现.它调用TPL类型的内部API.我也不想重现所有这些.
如果你想玩它,这是一个简短的repro:
static void Main()
{
Run().Wait();
}
static async Task Run()
{
Task[] tasks = new[] { CreateTask("ex1"), CreateTask("ex2") };
await Task.WhenAll(tasks);
}
static Task CreateTask(string message)
{
return Task.Factory.StartNew(() => { throw new Exception(message); });
}
Run Code Online (Sandbox Code Playgroud)
只抛出两个例外中的一个Run
.
请注意,Stack Overflow上的其他问题无法解决此特定问题.建议重复时请小心.
我已阅读TPL和任务库文档封面.但是,我仍然无法清楚地理解以下案例,现在我需要实施它.
我会简化我的情况.我IEnumerable<Uri>
的长度是1000.我必须使用它来请求它们HttpClient
.
我有两个问题.
Parallel.Foreach()
吗?Task
创建大量的最佳实践是什么?假设我使用Task.Factory.StartNew()
并将这些任务添加到列表中并等待所有这些任务.是否有一个功能(如TPL分区程序)控制最大任务的数量和HttpClient
我可以创建的最大值?在SO上有几个类似的问题,但没有人提到最大值.该要求仅使用具有最大HttpClient的最大任务.
先感谢您.
我有一个将在Parallel.Foreach中使用的异步方法.在异步方法中有等待任务.但是,在测试中,似乎没有等待行为,await Task没有完成.有什么问题?下面是代码.
public void method1()
{
Ilist<string> testList = new IList<string>(){"1","2","3"};
Parallel.ForEach(testList, ()=>
{
method2();
});
}
public async void method2()
{
await Task.run(()=>{ some other codes here });
}
Run Code Online (Sandbox Code Playgroud) 如果您需要并行运行多个异步I/O任务但需要确保不会同时运行多个XI/O进程,该怎么办?I/O处理前后的任务不应该有这样的限制.
这是一个场景 - 假设有1000个任务; 每个人都接受一个文本字符串作为输入参数; 转换该文本(预I/O处理)然后将转换后的文本写入文件.目标是使预处理逻辑利用100%的CPU /内核和任务的I/O部分以最大10度并行性运行(同时打开最多10个用于一次写入文件).
你能提供一个示例代码如何使用C#/ .NET 4.5吗?
http://blogs.msdn.com/b/csharpfaq/archive/2012/01/23/using-async-for-file-access-alan-berman.aspx
我想比较两种理论情景.为了这个问题,我简化了案例.但基本上它是典型的生产者消费者情景.(我专注于消费者).
我有一个很大的Queue<string> dataQueue
,我必须传输到多个客户端.
所以让我们从更简单的情况开始:
class SequentialBlockingCase
{
public static Queue<string> DataQueue = new Queue<string>();
private static List<string> _destinations = new List<string>();
/// <summary>
/// Is the main function that is run in its own thread
/// </summary>
private static void Run()
{
while (true)
{
if (DataQueue.Count > 0)
{
string data = DataQueue.Dequeue();
foreach (var destination in _destinations)
{
SendDataToDestination(destination, data);
}
}
else
{
Thread.Sleep(1);
}
}
}
private static void SendDataToDestination(string destination, string data)
{ …
Run Code Online (Sandbox Code Playgroud) 下面是Stephen Toub 编写的一个实现ForEachAsync
public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
{
return Task.WhenAll(
from partition in Partitioner.Create(source).GetPartitions(dop)
select Task.Run(async delegate {
using (partition)
while (partition.MoveNext())
await body(partition.Current);
}));
}
Run Code Online (Sandbox Code Playgroud)
指定 partitionCount 时应考虑哪些因素(dop
在本例中)?
硬件是否有所作为(内核数量、可用 RAM 等)?
数据/操作的类型是否影响计数?
我的第一个猜测是在一般情况下设置为dop
等于Environment.ProcessorCount
,但我的直觉告诉我这可能无关。