如何解决WaitUntil直到IF Cond
我正在使用并行Foreach。我也在foreach中称为webapi。我想控制来自api的响应。如果我获得了真值或某种价值,我想完成所有任务并进行每次迭代。
我在stackoverflow中进行搜索,但看不到任何响应。
Task<bool>[] tasks = new Task<bool>[customers.Count()];
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
ParallelOptions po = new ParallelOptions();
po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
Parallel.ForEach(customers,po,async (customer,state,index) =>
{
po.CancellationToken.ThrowIfCancellationRequested();
var filePath = Path.Combine(_hostingEnvironment.WebrootPath,"Photos",$"{customer.CustomerNumber}.jpg");
byte[] secondImageBytes = await System.IO.File.ReadAllBytesAsync(filePath).ConfigureAwait(false);
ByteArrayContent secondImage = new ByteArrayContent(secondImageBytes);
var test = await SomeFunction().ConfigureAwait(false);
if (test)
{
//cancel all foreach task
}
});
为了理解,请测试代码:
static async Task Main(string[] args)
{
Stopwatch watch = new Stopwatch();
watch.Start();
List<TaskItem> taskList = new();
taskList.Add(new TaskItem { Id = 1,Delay = 100,isOkey = true,Name = "Try 1" });
taskList.Add(new TaskItem { Id = 2,Delay = 2000,isOkey = false,Name = "Try 2" });
taskList.Add(new TaskItem { Id = 3,Name = "Try 3" });
taskList.Add(new TaskItem { Id = 4,Name = "Try 4" });
taskList.Add(new TaskItem { Id = 5,Name = "Try 5" });
taskList.Add(new TaskItem { Id = 6,Delay = 200,Name = "Try 6" });
taskList.Add(new TaskItem { Id = 7,Delay = 10000,Name = "Try 7" });
taskList.Add(new TaskItem { Id = 8,Name = "Try 8" });
taskList.Add(new TaskItem { Id = 9,Name = "Try 9" });
var control=await TestTask2Async(taskList);
Console.WriteLine("Result ="+control);
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalSeconds.ToString());
Console.ReadKey();
}
public static async Task<int> TestTaskAsync(List<TaskItem> taskList)
{
var matchedId = 0;
try
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var SoMetask = Task.Factory.StartNew(async () =>
{
await Task.WhenAll(taskList.AsEnumerable().Select(async item =>
{
token.ThrowIfCancellationRequested();
await Task.Delay(100);
await Task.Delay(1000);
await Task.Delay(item.Delay);
Console.WriteLine("Process for " + item.Id);
if (item.isOkey)
{
Console.WriteLine("Founded " + item.Id);
matchedId = item.Id;
tokenSource.Cancel();
}
}));
},token);
await SoMetask.Result;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return matchedId;
}
public static async Task<int> TestTask2Async(List<TaskItem> taskList)
{
var matchedId = 0;
try
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
await Task.WhenAll(taskList.AsEnumerable().Select(async item =>
{
token.ThrowIfCancellationRequested();
await Task.Delay(100).ConfigureAwait(false);
await Task.Delay(1000).ConfigureAwait(false);
await Task.Delay(item.Delay).ConfigureAwait(false);
Console.WriteLine("Process for " + item.Id);
if (item.isOkey)
{
Console.WriteLine("Founded " + item.Id);
matchedId = item.Id;
tokenSource.Cancel();
}
}));
}
catch (Exception)
{
}
return matchedId;
}
public class TaskItem
{
public int Id { get; set; }
public int Delay { get; set; }
public string Name { get; set; }
public bool isOkey { get; set; }
}
-
结果:
处理4
5次处理
处理1
3次处理
成立1
6次处理
处理2
处理7
处理9
处理8
结果= 1
11.2402357
但是我想如果Found(bla)建立了,所有的任务都会死掉,我不想在Found建立后看到(bla)的过程。
在这个例子中,我只想看看:
处理4
5次处理
处理1
3次处理
成立1
结果= 1
1.2402357
解决方法
Parallel.ForEach
不适用于async
-await
。
所有项目都到达第一个未完成的Parallel.ForEach
时,await
将终止。
尝试以下方法:
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
await Task.WhenAll(customers.Select(async customer =>
{
token.ThrowIfCancellationRequested();
var filePath = Path.Combine(_hostingEnvironment.WebRootPath,"Photos",$"{customer.CustomerNumber}.jpg");
var secondImageBytes = await File.ReadAllBytesAsync(filePath).ConfigureAwait(false);
var secondImage = new ByteArrayContent(secondImageBytes);
var test = await SomeFunction().ConfigureAwait(false);
if (test)
{
tokenSource.Cancel();
}
}));
此外,请勿将Task.Factory.StartNew
-async
与await
一起使用。请改用Task.Run
。
关于取消标记,您需要了解的一件事是它表明了取消的意图,但它本身并不能取消任何东西。该代码需要对其进行检查并以所需的任何方式取消。
尝试一下:
public static async Task<int> TestTask2Async(List<TaskItem> taskList)
{
var matchedId = 0;
try
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
await Task.WhenAll(taskList.AsEnumerable().Select(async item =>
{
token.ThrowIfCancellationRequested();
// add token to the call to Task.Delay
await Task.Delay(100,token).ConfigureAwait(false);
await Task.Delay(1000,token).ConfigureAwait(false);
await Task.Delay(item.Delay,token).ConfigureAwait(false);
// check it again
token.ThrowIfCancellationRequested();
Console.WriteLine("Process for " + item.Id);
if (item.isOkey)
{
// cancel as soon as the condition has been met
tokenSource.Cancel();
Console.WriteLine("Founded " + item.Id);
matchedId = item.Id;
}
}));
}
catch (Exception ex)
{
}
return matchedId;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。