简体   繁体   中英

Right way of using TPL for this specific constellation ( Continuous parallel Tasks )

i hope i can get some help here, tried different things that work, but always with some problems. What would be the best way to achieve with the sample code the following:

Task A + B + C should run parallel, but Task B should start with a small delay to task A. Depending on the result of the single Tasks devsearch/conssearch, they should just restart themselves or start task "GO". GO will run only once and will restart the calling task.

As already said, what would be the best way to do this. Is Parallel.Invoke here the suitable option? Should i switch to Tasks and move it to the Main Section?

I really appreciate any help. Thanks in Advance. Please do not care about small faults in the tasks or the details, just built this as example to do not have it too complex.

UPDATE/Additional Information:

I have a Windows Form Application. The logic is the following:

  1. I have a start button, which starts "public async void button1_Click"
  2. I have 3 Tasks

    • "private async Task conssearch"
    • "private async Task devsearch"
    • "private async Task GO"

    For the tasks conssearch and devsearch i give the parameters who is the sender, a bool, an Account and an Array. In the tasks i perform asynch http requests with await. This request is done for each item in the Array. For the http requests i need logindata, this is passed via the Account. I can login multiple times ( Cookiehandling etc. is done and working ), that is why i want to run conssearch parallel at the same time. The delay between the parallel execution of conssearch is needed, bcause i don´t want to have the same results. I have a rps limit per account, that is why i have await.delay within the single tasks.

    So in summary i want to start parallel conssearch x 2 and devsearch when i press the Start Button.

  3. Now Every single task should run independant from each other.

    • If i get in the Tasks conssearch and devsearch the result i am expecting, i will start "private async Task GO" and pass the same parameters. This is done bcause i want that "private async Task GO" starts the calling Task again after it is finished.
    • If i do not get the expected result, the Task should restart

I hope it is now a bit better understandable what i am trying to do.

public async void button1_Click(object sender, EventArgs e)
    {

            while (true)
            {

                Parallel.Invoke(
                   () => {
                        Task taskA = Task.Factory.StartNew(() => conssearch("cons", false, Account1, devArr));
                        System.Threading.Thread.Sleep(335);
                        Task taskB = Task.Factory.StartNew(() => conssearch("cons", false, Account2, devArr));

                        taskA.Wait();
                        taskB.Wait();
                    },

                    () => Task.Run(() => devsearch("dev", false, Account3, devArr)),

                    );

        }

    }



    private async Task conssearch(object sender, bool GO, string acc, Array[] devArr)
    {

                for (int i = 0; i < devArr.Length; i++)
                {

                    // Do some HTTP here....

           If ....
           GO = True;
                }
               await Task.Delay(100);

                    if (GO)
                    {
                        listView1.BeginInvoke(new MethodInvoker(() => listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent)));
                        listView2.BeginInvoke(new MethodInvoker(() => listView2.Items.Clear()));                      
                        GO("cons", acc, devArr);
                    }
                        else
                        {
                        //conssearch("cons", false, acc, devArr)
                        }
        }




    private async Task devsearch(object sender, bool GO, string acc, Array[] devArr)
    {

                 for (int i = 0; i < devArr.Length; i++)
                 {

                    // Do some HTTP here....

                        If ....
                        GO = True;
               }
               await Task.Delay(100);

                if (GO)
                {
                    listView1.BeginInvoke(new MethodInvoker(() => listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent)));
                    listView2.BeginInvoke(new MethodInvoker(() => listView2.Items.Clear()));
                    GO("cons", acc, devArr);
                }
                    else
                    {
                    //devsearch("dev", false, acc, devArr)
                    }
    }


    private async Task GO(object sender, string acc, Array[] devArr)
      {

{
                          // Do some HTTP here....
            }
           await Task.Delay(100); 

              if (sender == "tra")
                await conssearch(sender, false, client, devArr);
              else  
                await devsearch(sender, false, client, devArr);

      }

I'm going to focus only on running the three tasks, nothing else.

First of all, starting one task, waiting a constant amount of time and then starting a second task sounds suspicious. What is the purpose of the delay? I can't think of anything that would make the most sense to represent this way.

Now, combining Parallel and Task usually doesn't make much sense. If one of the Parallel methods works for you, use that, not Task s. If you need something more complicated, use Task s.

In your case, since you can use await , I would take advantage of that: have one async method that starts the conssearch Task s with the delay. Then, in another method, call that method, start the devsearch Task and wait for both to complete. Something like:

async Task RunConsSearches()
{
    var taskA = Task.Run(() => ConsSearch("cons", false, Account1, devArr));
    await Task.Delay(335);
    var taskB = Task.Run(() => ConsSearch("cons", false, Account2, devArr));

    await Task.WhenAll(taskA, taskB);
}

…

var consSeachTask = RunConsSearches();
var devSearchTask = Task.Run(() => DevSearch("dev", false, Account3, devArr));
await Task.WhenAll(consSeachTask, devSearchTask);

Even better approach would be to convert ConsSearch and DevSearch to proper async , but it's difficult to tell how hard would that be.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM