首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >WaitUntil IF Cond

WaitUntil IF Cond
EN

Stack Overflow用户
提问于 2020-11-05 10:46:58
回答 1查看 91关注 0票数 0

我在用paralel Foreach。同时,我在前额调用了webapi。我想控制api的响应。如果我得到了真或某物的价值,我想完成所有的任务,并提前迭代。

我搜索堆叠溢出,但我看不到任何反应。

代码语言:javascript
运行
复制
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
    }
});

为了理解,测试代码:

代码语言:javascript
运行
复制
  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, Delay = 100, isOkey = false, Name = "Try 3" });
        taskList.Add(new TaskItem { Id = 4, Delay = 100, isOkey = false, Name = "Try 4" });
        taskList.Add(new TaskItem { Id = 5, Delay = 100, isOkey = false, Name = "Try 5" });
        taskList.Add(new TaskItem { Id = 6, Delay = 200, isOkey = false , Name = "Try 6" });
        taskList.Add(new TaskItem { Id = 7, Delay = 10000, isOkey = false, Name = "Try 7" });
        taskList.Add(new TaskItem { Id = 8, Delay = 10000, isOkey = false, Name = "Try 8" });
        taskList.Add(new TaskItem { Id = 9, Delay = 10000, isOkey = false, 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

但是我想如果成立(bla),所有的任务都将是死亡,我不想看到(bla)在创建后的过程。

对于这个例子,我只想看到:

4种工艺

5种工艺

工艺1

3种工艺

成立1

结果=1

1.2402357

EN

回答 1

Stack Overflow用户

发布于 2020-11-05 18:52:32

Parallel.ForEach的设计并不是为了与async-await一起工作.

一旦到达所有项目的第一个未完成的Parallel.ForEach,该await就会终止。

试一试:

代码语言:javascript
运行
复制
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.StartNewasync-await结合使用。使用Task.Run代替。

关于取消令牌,您需要知道的一件事是,它表明了取消的意图,但它本身并没有取消任何东西。代码需要检查它并以任何需要的方式取消它。

试试这个:

代码语言:javascript
运行
复制
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;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64695602

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档