mercredi 10 janvier 2018

How to check if specific condition is met before running a Task?

The context is the following. I am doing an application to download stuff. So there is a setting to set maximum downloads.

This is how I handle things right now: I create the object for the download class as following:

var downloader = new Download(txtUserAgent.Text, _proxy.GetWebProxy(), requestTimeout, txtDownloadFolder.Text, _cancellationToken);

It contains a property to return the total downloads made from that object, called:

public int TotalCount
{
    get { return _totalCount; }
}

And then, I do this:

using (SemaphoreSlim semaphore = new SemaphoreSlim(int.Parse(txtThreads.Text)))
            {
                var tasks = new List<Task>();
                foreach (ListViewItem item in lvInput.Items)
                {
                    await semaphore.WaitAsync();

                    try
                    {
                        // this checks if the total downloads is enabled and if the download count isn't reached, but it doesn't work apparently, because the tasks all get started anyway and when the limit is reached, it'll run the other tasks throwing a cancelledtask exception (which is what I do when limit is reached)
                        if (cbTotalDownloads.Checked && Int32.Parse(txtTotalDownloads.Text) >= downloader.TotalCount)
                        {
                            tasks.Add(
                                Task.Run(async () =>
                                {
                                    switch (item.SubItems[0].Text)
                                    {
                                        case "Url":
                                            try
                                            {
                                                await downloader.Download(item.SubItems[1].Text, InputType.Url,
                                                    mediaFilter);
                                            }
                                            catch (Exception ex)
                                            {
                                                Log(ex.Message, nameof(LogType.Error));
                                            }

                                            break;
                                        // other cases
                                    }
                                }, _cancellationToken)
                            );
                        }
                        else
                        {
                            return;
                        }
                    }
                    catch (Exception)
                    {
                        Console.WriteLine("testex");
                    }
                    finally
                    {
                        semaphore.Release();
                    }
                }

                await Task.WhenAll(tasks);

My question: How do I check a condition before running the tasks/while running OR stop the remaining ones from executing if it's no longer needed?

Another idea I thought of is to increase a counter inside the foreach as well, but it won't work, because one item in the lvInput could contain multiple Urls, so it's not easy to keep track of how many downloads to increase by.

Aucun commentaire:

Enregistrer un commentaire