Click here to Skip to main content
14,336,465 members
Rate this:
Please Sign up or sign in to vote.
See more:
please, help me out what i thought was the answer just falls back to the same thing. I'm a self taught programmer who havn't known much. The timer all run same thing cause it uses ui thread. Please, how do i run two timers to take from a list and browse the web using the info from the list?
My problem is that they all use same item and this is not good because of repitition and i don't even know how to channel 'timers.timer' and 'threading.timer' into this matter to bail me out. Please, your help is greatly needed.

What I have tried:

just inputing into webbrowser bt using synclock with three timers running simultaneously bt they seem to use same item from list because they run on ui thread
Posted
Updated 2-Mar-19 22:23pm
Comments
Slacker007 1-Mar-19 10:09am
   
Is this task a little advanced for a beginner? Something to consider.
Member 10285969 1-Mar-19 21:11pm
   
not that advanced. The problem is how to run multiple thread.timer at intervals cause i dönt know how
Gerry Schmitz 3-Mar-19 12:22pm
   
You're getting "solutions"; but since you haven't made clear on why you think you need 3 timers you are probably "solving" the wrong "problem".

There is usually more than one way to solve something, with some solutions a lot better than others; but not if you're not clear in the first place.
CHill60 5-Mar-19 6:03am
   
When I advised you to start a new thread I also advised you to post the code. Without seeing your code we cannot possibly help you with why you are always using the same item.
Rate this:
Please Sign up or sign in to vote.

Solution 2

Here is an alternative method based on Asynchronous calls using Async...Await[^].

Async...Await uses the ThreadPool to manage the multitasking. The number of threads executed simultaneously is dependant on the CPU and the number of cores. If you want to change the default setting, the following documentation will explain how: ThreadPool.SetMinThreads(Int32, Int32) Method (System.Threading) | Microsoft Docs[^]

The WebClient[^] class has a DownloadStringTaskAsync[^] method that we can use. We can force the method to run off the UI thread by calling ConfigureAwait(false)[^].

To help us visualize how this work, let us wrap the call in a method:
private static async Task<Tuple<string, string>> GetUrlAsync(Uri url)
{
    Console.WriteLine("thisIsAsyncStart: " 
        + Thread.CurrentThread.ManagedThreadId);

    // make our call on another thread
    var result = await new WebClient()
        .DownloadStringTaskAsync(url).ConfigureAwait(false);

    Console.WriteLine("thisIsAsyncEnd: " + Thread.CurrentThread.ManagedThreadId);

    // return both the uri passed and the data returned
    return new Tuple<string, string>(url.ToString(), result);

    // we return to the UI thread when we exit this method
}

Next, we need a few URIs to call:
private static List<Uri> urls = new List<Uri>()
    {
        new Uri("https://www.codeproject.com", UriKind.Absolute),
        new Uri("https://apple.com", UriKind.Absolute),
        new Uri("https://xamarin.com", UriKind.Absolute),
        new Uri("https://nokia.com", UriKind.Absolute),
        new Uri("https://samsung.com", UriKind.Absolute),
        new Uri("https://www.microsoft.com", UriKind.Absolute),
        new Uri("https://www.codeproject.com", UriKind.Absolute),
        new Uri("https://apple.com", UriKind.Absolute),
        new Uri("https://xamarin.com", UriKind.Absolute),
        new Uri("https://nokia.com", UriKind.Absolute),
        new Uri("https://samsung.com", UriKind.Absolute),
        new Uri("https://www.microsoft.com", UriKind.Absolute),
        new Uri("https://www.codeproject.com", UriKind.Absolute),
        new Uri("https://apple.com", UriKind.Absolute),
        new Uri("https://xamarin.com", UriKind.Absolute),
        new Uri("https://nokia.com", UriKind.Absolute),
        new Uri("https://samsung.com", UriKind.Absolute),
        new Uri("https://www.microsoft.com", UriKind.Absolute),
        new Uri("https://www.codeproject.com", UriKind.Absolute),
        new Uri("https://apple.com", UriKind.Absolute),
        new Uri("https://xamarin.com", UriKind.Absolute),
        new Uri("https://nokia.com", UriKind.Absolute),
        new Uri("https://samsung.com", UriKind.Absolute),
        new Uri("https://www.microsoft.com", UriKind.Absolute),
        new Uri("https://www.codeproject.com", UriKind.Absolute),
        new Uri("https://apple.com", UriKind.Absolute),
        new Uri("https://xamarin.com", UriKind.Absolute),
        new Uri("https://nokia.com", UriKind.Absolute),
        new Uri("https://samsung.com", UriKind.Absolute),
        new Uri("https://www.microsoft.com", UriKind.Absolute),
    };

Now there are two way that I will demonstrate managing multiple tasks at once.

1. WhenAll[^] - Creates a task that will complete when all of the Task objects in an array have completed
private static async Task RunWhenAllAsync()
{
    var tasks = new List<Task<Tuple<string, string>>>();

    foreach (var url in urls)
    {
        tasks.Add(GetUrlAsync(url));
    }

    await Task.WhenAll(tasks.ToArray());

    foreach (var task in tasks)
    {
        var result = task.Result;
        Console.WriteLine($"id: {task.Id} | url {task.Result.Item1} > length: {task.Result.Item2.Length}");
    }
}

Output:
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncEnd: 13
thisIsAsyncEnd: 11
thisIsAsyncEnd: 13
thisIsAsyncEnd: 13
thisIsAsyncEnd: 11
thisIsAsyncEnd: 16
thisIsAsyncEnd: 11
thisIsAsyncEnd: 12
thisIsAsyncEnd: 16
thisIsAsyncEnd: 15
thisIsAsyncEnd: 12
thisIsAsyncEnd: 12
thisIsAsyncEnd: 13
thisIsAsyncEnd: 11
thisIsAsyncEnd: 16
thisIsAsyncEnd: 11
thisIsAsyncEnd: 11
thisIsAsyncEnd: 16
thisIsAsyncEnd: 14
thisIsAsyncEnd: 14
thisIsAsyncEnd: 13
thisIsAsyncEnd: 12
thisIsAsyncEnd: 15
thisIsAsyncEnd: 14
thisIsAsyncEnd: 12
thisIsAsyncEnd: 13
thisIsAsyncEnd: 14
thisIsAsyncEnd: 11
thisIsAsyncEnd: 15
thisIsAsyncEnd: 11
id: 1 | url https://www.codeproject.com/ > length: 96485
id: 3 | url https://apple.com/ > length: 53646
id: 5 | url https://xamarin.com/ > length: 149548
id: 7 | url https://nokia.com/ > length: 73246
id: 9 | url https://samsung.com/ > length: 106147
id: 11 | url https://www.microsoft.com/ > length: 1020
id: 13 | url https://www.codeproject.com/ > length: 96479
id: 15 | url https://apple.com/ > length: 53646
id: 17 | url https://xamarin.com/ > length: 149548
id: 19 | url https://nokia.com/ > length: 73246
id: 21 | url https://samsung.com/ > length: 106147
id: 23 | url https://www.microsoft.com/ > length: 1020
id: 25 | url https://www.codeproject.com/ > length: 96485
id: 27 | url https://apple.com/ > length: 53646
id: 29 | url https://xamarin.com/ > length: 149548
id: 31 | url https://nokia.com/ > length: 73246
id: 33 | url https://samsung.com/ > length: 106147
id: 35 | url https://www.microsoft.com/ > length: 1020
id: 37 | url https://www.codeproject.com/ > length: 96485
id: 39 | url https://apple.com/ > length: 53646
id: 41 | url https://xamarin.com/ > length: 149548
id: 43 | url https://nokia.com/ > length: 73246
id: 45 | url https://samsung.com/ > length: 106147
id: 47 | url https://www.microsoft.com/ > length: 1020
id: 49 | url https://www.codeproject.com/ > length: 96485
id: 51 | url https://apple.com/ > length: 53646
id: 53 | url https://xamarin.com/ > length: 149548
id: 55 | url https://nokia.com/ > length: 73246
id: 57 | url https://samsung.com/ > length: 106147
id: 59 | url https://www.microsoft.com/ > length: 1020

Benefits:

  • code is very simple
  • the UI thread won't be blocked
  • the tasks run in async on seperate threads to the UI
  • the results are in the order the tasks were created, not the order they completed

Disadvantages:

  • execution will wait until all tasks are completed
  • the user won't receive any progress feedback

2. WaitAny[^] - Waits for any of the provided Task objects to complete execution.
private static readonly object lockObj = new object();

private static async Task RunWaitAnyAsync()
{
    var tasks = new List<Task<Tuple<string, string>>>();

    foreach (var url in urls)
    {
        tasks.Add(GetUrlAsync(url));
    }

    while (tasks.Count > 0)
    {
        // index of task completed
        var index = Task.WaitAny(tasks.ToArray());

        // get the task
        var task = tasks[index];

        if (task.IsCompleted) // success
        {
            // retrieve the result
            var result = task.Result;

            // display
            Console.WriteLine($"id: {task.Id} | url {task.Result.Item1} > length: {task.Result.Item2.Length}");

        }
        else if (task.IsFaulted)
        {
            // handled failed here...
        }

        // block collisions & remove the task from the execution list
        lock (lockObj) tasks.Remove(task);
    }
}

Output:
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncStart: 1
thisIsAsyncEnd: 12
thisIsAsyncEnd: 13
id: 11 | url https://www.microsoft.com/ > length: 1020
id: 23 | url https://www.microsoft.com/ > length: 1020
thisIsAsyncEnd: 13
id: 35 | url https://www.microsoft.com/ > length: 1020
thisIsAsyncEnd: 13
id: 47 | url https://www.microsoft.com/ > length: 1020
thisIsAsyncEnd: 11
id: 59 | url https://www.microsoft.com/ > length: 1020
thisIsAsyncEnd: 13
id: 3 | url https://apple.com/ > length: 53646
thisIsAsyncEnd: 16
id: 15 | url https://apple.com/ > length: 53646
thisIsAsyncEnd: 15
id: 27 | url https://apple.com/ > length: 53646
thisIsAsyncEnd: 15
id: 7 | url https://nokia.com/ > length: 73246
thisIsAsyncEnd: 12
id: 39 | url https://apple.com/ > length: 53646
thisIsAsyncEnd: 13
thisIsAsyncEnd: 16
id: 9 | url https://samsung.com/ > length: 106147
id: 21 | url https://samsung.com/ > length: 106147
thisIsAsyncEnd: 13
id: 31 | url https://nokia.com/ > length: 73247
thisIsAsyncEnd: 14
id: 19 | url https://nokia.com/ > length: 73246
thisIsAsyncEnd: 15
id: 55 | url https://nokia.com/ > length: 73247
thisIsAsyncEnd: 17
id: 45 | url https://samsung.com/ > length: 106148
thisIsAsyncEnd: 16
id: 33 | url https://samsung.com/ > length: 106148
thisIsAsyncEnd: 17
id: 57 | url https://samsung.com/ > length: 106147
thisIsAsyncEnd: 16
id: 43 | url https://nokia.com/ > length: 73247
thisIsAsyncEnd: 14
id: 51 | url https://apple.com/ > length: 53646
thisIsAsyncEnd: 11
id: 41 | url https://xamarin.com/ > length: 149548
thisIsAsyncEnd: 12
id: 17 | url https://xamarin.com/ > length: 149548
thisIsAsyncEnd: 16
id: 53 | url https://xamarin.com/ > length: 149548
thisIsAsyncEnd: 15
id: 5 | url https://xamarin.com/ > length: 149548
thisIsAsyncEnd: 15
id: 1 | url https://www.codeproject.com/ > length: 96485
thisIsAsyncEnd: 17
id: 29 | url https://xamarin.com/ > length: 149548
thisIsAsyncEnd: 15
id: 25 | url https://www.codeproject.com/ > length: 96479
thisIsAsyncEnd: 17
id: 49 | url https://www.codeproject.com/ > length: 96479
thisIsAsyncEnd: 11
id: 13 | url https://www.codeproject.com/ > length: 96485
thisIsAsyncEnd: 16
id: 37 | url https://www.codeproject.com/ > length: 96485

Benefits:

  • the UI thread won't be blocked
  • the tasks run in async on seperate threads to the UI
  • the results are in the order of completion, not the order they were executed
  • Feedback is imediate as a task completes giving the user progress feedback

Disadvantages:

  • code is more involved

NOTE: If you have hundreds or thousands of pages that you want to pull down, I have a better ramp up function for not overloading the Threadpool system & CPU.
   
v2
Comments
Member 10285969 4-Mar-19 13:01pm
   
the site uses javascript thats the downside.
Graeme_Grant 4-Mar-19 17:43pm
   
So you're wanting to do page scraping? the solution above will do what you want to get the page...
Member 10285969 5-Mar-19 0:40am
   
its a single page where you input strings that brings result with javascript
Graeme_Grant 5-Mar-19 1:31am
   
You're describing two different issues here:
1. How to download multiple URI in the background - ie: multi-threaded.
2. How to determine how to get the correct data based on the call required

For part 1, still, the above solution will do what you want.

For part 2, you need to do some research... Use Fiddler[^], which is a traffic sniffer, and watch the ajax calls made by the javascript and the responses the server issues ... then you know what URI to call with headers, cookies, etc...
Member 10285969 5-Mar-19 22:11pm
   
i have tried fiddler but didnt get anything meaningful but will try again and let you know the outcome.
Graeme_Grant 5-Mar-19 22:21pm
   
for a higher level ... use your web browser "F12" tools, there is a traffic sniffer there too
Member 10285969 6-Mar-19 14:05pm
   
how can i write you privately? I will want to give you the site so you see if you can help me capture its post request because to me its not possible. Either encrypted and i dont want to put it publicly. Please.
Dnt knw if you can delete a comment..
Graeme_Grant 6-Mar-19 16:07pm
   
That is a separate question to the one already answered. Please mark this one as answered that addresses downloading multiple pages in the background. The issue that you now want answering needs to be opened as a new question.
Richard Deeming 5-Mar-19 11:42am
   
NB: Task.WhenAll has an overload that takes an IEnumerable<Task>, so there's no need for the .ToArray() call:
await Task.WhenAll(tasks);

It also has an overload for tasks with a return value:
private static async Task RunWhenAllAsync()
{
    IEnumerable<Tuple<string, string>> tasks = urls.Select(GetUrlAsync);
    Tuple<string, string>[] results = await Task.WhenAll(tasks);
    
    foreach (Tuple<string, string> result in results)
    {
        Console.WriteLine($"url {result.Item1} > length: {result.Item2.Length}");
    }
}
Graeme_Grant 5-Mar-19 13:07pm
   
I don't like using WhenAll and only included it as an example. Thanks for pointing that out for the OP and others. :)
Rate this:
Please Sign up or sign in to vote.

Solution 1

Unless you specifically start a new thread, all processing happens on the original - UI - thread. And if you do start additional threads, they cannot directly access any UI components (including WebBrowser controls) without raising a cross threading exception.

Instead of using WebBrowsers and timers, use BackgroundWorker[^] (They are a separate thread, but they make it easy to communicate results to the UI thread via progress / exit events) and use the WebClient class[^] to interact with the webpage in each thread.

If the background threads need to wait for a specific time, you can use Thread.Sleep[^] to do that without needing timers.
   
Comments
Member 10285969 4-Mar-19 12:53pm
   
its a nice idea but the setback is that the website i am working with is mainly using javascript to produce results i need extracted thats why i go for webbrowser with its click event.

Another thing is when using timer, you ensure it delivers or initiates the click to bring out the result by including a 'timer1.stop()' at the beginning of the tick event so is this same with backgroundworker? I like the idea really because i could use it to handle webbrowser click event.

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




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100