Click here to Skip to main content
15,887,270 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have an user control in the main window with a button (Button1).
The Button1_click event starts to fetch data from a webservice (runs >1 hour).

To reduce time a want to run 10 tasks to fetch the data.

In my example the method DoWork() does not start immediatly.
It starts after the Button1_click event is done.
So the post process has no data.

How can I implement the wait function to wait until all threads are finished?

What I have tried:

UserControl:
List<string> fetchedData = new List<string>();

private void Button1_Click(object sender, System.Windows.RoutedEventArgs e)
{
    fetchedData.Clear();
    FetchData();

    // problem: 
    // (pseudo code) wait until all data is fetched
    while(true) { break; }

    // Post process
    foreach (var item in fetchedData) {
      // do something with the data (complete data list!)
    }
}

private void FetchData() 
{
  var threads = new Thread[10];

  for (int segment = 0; segment <= 9; segment++)
  {
    var worker = new ThreadStart(
        ()=>this.Dispatcher.BeginInvoke(
            DispatcherPriority.Normal,
            (ThreadStart)delegate ()
            {
                DoWork(iSegment); //executed AFTER exiting the button1_click event
            }
        )
    );

    threads[segment] = new Thread(worker);
    threads[segment].Start();                     
  }
}

private void DoWork (int segment) {
   fetchedData.Add( Helpers.GetWebserviceData(segment) );

   // output some data to the mainWindow to see the actual process
   Helpers.mainWindow.LabelStatus.Content = "Current segment: " + i.ToString();
}
Posted
Updated 4-Oct-18 2:59am

 
Share this answer
 
Stephen Cleary has great articles too about Asynchronous Programming in .NET: Async and Await[^]
 
Share this answer
 
v2
Thanks for your comments. I have build a simple example which calls some methods with delays. The output is as expected in the right order (due to the different delays).

My Problem is now:
I have a webservice in a external static class (see below).
This wrapper has no async keyword and there is no async call in the webservice client (webreference to external service).

Would it help to put the Wrapper in a instanced class so that the every task calls is own instance of the wrapper?

public static class Wrapper {
   public static string CallWebservice(string param) {
      var client = new Webservice.Client();
      // takes up to 3 seconds per call
      return client.Method(param);
   }
}

using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;

namespace AsyncTest
{
    public static class Helpers
    {
        public static MainWindow mainWindow = null;
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Helpers.mainWindow = this;
        }

        public static void AddLog(string text)
        {
            Helpers.mainWindow.Dispatcher.Invoke(
                () => Helpers.mainWindow.LblOutput.Content += DateTime.Now.ToString() + $" [{text}]\r\n",
                DispatcherPriority.Background
            );
        }

        private async void ButtonDoAsync_Click(object sender, RoutedEventArgs e)
        {
            AddLog("Button Click:Start");

            StartAsync();

            for (var i = 0; i < 5; i++)
            {
                AddLog($"Button Click:Wait {i}");
                await Task.Delay(500);
            }

            AddLog("Button Click:End");
        }

        static async void StartAsync()
        {
            var tasks = new Func<Task>[]
                {
                    () => DoSomethingAsync("t1",800),
                    () => DoSomethingAsync("t2",350),
                    () => DoSomethingAsync("t3",450)
                };

            await Task.WhenAll(tasks.Select(task => task()).ToArray());
        }

        static async Task DoSomethingAsync(string taskId, int delay)
        {
            for (var i = 0; i < 5; i++)
            {
                AddLog(Wrapper.CallWebservice(taskID));  // no async here
                AddLog($"Async {taskId} {i}");
                await Task.Delay(delay);
            }
        }
    }
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900