• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 4493
  • Last Modified:

c# Tasks - How to wait for events

Hi,

I have some code which initiates a download. This results in one of the following async events being triggered. I need the application to wait for one of these events before continuing.

Is this a job for tasks? Can I create a task with my download code which returns 'task complete' when one of the 3 events below fire?

(stdFile_.saver as _IStreamCollectorEvents_Event).stopped += (collector) =>
{
	Console.WriteLine("Download stopped");
};
(stdFile_.saver as _IStreamCollectorEvents_Event).failed += (sender, error) =>
{
	Console.WriteLine("Download failed");
};
(video as _IStream_Events_Event).stopped += (s) =>
{
	Console.WriteLine("Download Complete!");
};

Open in new window

0
mhdi
Asked:
mhdi
  • 2
2 Solutions
 
chaauCommented:
You can use a WaitHandle class. Register it before the download starts. Then just use the WaitOne() method in the main program. I recommend you use the version of the method where you can specify the timeout to make sure your program does not forever. The pseudo code will be similar to this:

Create a global variable:
static AutoResetEvent autoEvent = new AutoResetEvent(false);

Open in new window

Then in your main program start your download and wait:
       Console.WriteLine("Main starting.");

        // your code for asynchronous download here. 

        // Wait for work method to signal. 
        if(autoEvent.WaitOne(1000))
        {
            Console.WriteLine("download event signaled.");
        }
        else
        {
            Console.WriteLine("Timed out waiting for download");
        }
        Console.WriteLine("Main ending.");

Open in new window

And your evens all do the same:
(stdFile_.saver as _IStreamCollectorEvents_Event).stopped += (collector) =>
{
	Console.WriteLine("Download stopped");
	autoEvent.Set();
};
(stdFile_.saver as _IStreamCollectorEvents_Event).failed += (sender, error) =>
{
	Console.WriteLine("Download failed");
	autoEvent.Set();
};
(video as _IStream_Events_Event).stopped += (s) =>
{
	Console.WriteLine("Download Complete!");
	autoEvent.Set();
};
                                  

Open in new window

You may also wish to introduce a global string variable for status to indicate the result of your download
0
 
Vel EousResearch & Development ManagerCommented:
Ideally you do not want to block whilst the operation is in progress, so making use of the TPL is a viable option (there is also the older and still valid BackgroundWorker class).

The following example should get you most of the way to what you are looking for:

namespace EE.Q_28547351.ConsoleApp
{
    using System;
    using System.Threading;
    using System.Threading.Tasks;

    internal class Program
    {
        private static CancellationTokenSource cts;

        private static void Main(string[] args)
        {
            // Create a new CancellationTokenSource so that the task can be cancelled if required
            cts = new CancellationTokenSource();
            // Start the operation
            var task =
                Task.Run(() => DownloadOperation(new Progress<ProgressReport>(ReportProgress)), cts.Token)
                    .ContinueWith(TaskComplete);

            Console.WriteLine("Task running ...");
            Console.WriteLine("Press any key to cancel the process");
            Console.ReadKey();

            // Cancel the task
            cts.Cancel();

            Console.ReadKey();
        }

        // Download operation simulates where you would perform your long running process
        // This is where you will perform your download
        // I have added a delay to simulate a long running download
        private static async Task<bool> DownloadOperation(IProgress<ProgressReport> progress)
        {
            const int totalAmount = 10;
            for (var i = 1; i <= totalAmount; i++)
            {
                if (cts.IsCancellationRequested)
                {
                    return false;
                }
                await Task.Delay(1000);
                progress.Report(new ProgressReport
                {
                    CurrentProgressAmount = i,
                    TotalProgressAmount = totalAmount,
                    Message = i == totalAmount ? "All done" : "More to do"
                });
            }

            return true;
        }

        private static void ReportProgress(ProgressReport report)
        {
            Console.WriteLine(report);
        }

        private static void TaskComplete(Task<bool> task)
        {
            // Do something when the task completes
            Console.WriteLine(task.Result);
        }
    }

    // Encapsulates progress information and is used by the IProgress<T> interface
    internal class ProgressReport
    {
        public int CurrentProgressAmount { get; set; }
        public int TotalProgressAmount { get; set; }
        public string Message { get; set; }

        public override string ToString()
        {
            return string.Format("Processing {0} of {1}. {2}", this.CurrentProgressAmount, this.TotalProgressAmount,
                this.Message);
        }
    }
}

Open in new window

0
 
mhdiAuthor Commented:
Apologies for the late reply guys.

@chaau - I need the ability to signal the main thread whether the download completed successfully or not. Can I do this with the "AutoResetEvent"?  Or do I keep a separate variable which holds the download status. eg "bool downloadComplete = false" which gets changed to "true" when the download complete event is fired.

@Tchuki - I like your proposed solution, but how do I tie in the events mentioned in my top post?
0
 
chaauCommented:
You just need the AutoResetEvent, and set it

autoEvent.Set();
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now