Solved

c# Tasks - How to wait for events

Posted on 2014-10-29
4
2,205 Views
Last Modified: 2014-12-15
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
Comment
Question by:mhdi
  • 2
4 Comments
 
LVL 24

Accepted Solution

by:
chaau earned 250 total points
ID: 40412359
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
 
LVL 14

Assisted Solution

by:Vel Eous
Vel Eous earned 250 total points
ID: 40412735
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
 

Author Comment

by:mhdi
ID: 40423311
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
 
LVL 24

Expert Comment

by:chaau
ID: 40423359
You just need the AutoResetEvent, and set it

autoEvent.Set();
0

Featured Post

Resolve Critical IT Incidents Fast

If your data, services or processes become compromised, your organization can suffer damage in just minutes and how fast you communicate during a major IT incident is everything. Learn how to immediately identify incidents & best practices to resolve them quickly and effectively.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Google Directions API to Map URL -C#? 3 38
Adding bootstrap to only Content page and NOT master page 1 51
Where is this file? 3 26
Get month and date in a format 4 35
This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question