Dave, thanks for replying to my original post. Im sure there are many ways
to achieve the same thing and at the end of the day Ill learn whatever
works. Ive copied your code and Richards code, both of which have shown me
how delegates and asynchronous operations work.
Thanks for your help,
Grant
"Dave" <NOSPAM-dave@dotcomdatasolutions.com> wrote in message
news:%23MAqgpkTFHA.3840@tk2msftngp13.phx.gbl...[color=blue]
> The code I supplied was to illustrate how to use a delegate
> asynchronously, in a simple approach. I used a design pattern that would
> allow the developer to call the "UpdateProgress" method from a class that
> has a reference to the form without caring about the "logic" involved in
> updating the Form's controls.
>
> Thread-Safety
> Encapsulation
> Win32 programming
>
> Grant:
>
> In my previous code sample I have illustrated how you can use a delegate.
> I'm sorry if it was unclear. I have attached a simpler approach below.
>
> The code below will also address this question:
>[color=green]
>> thing.countUpToaMillionOrSomething(dlgate). What method name is it
>> expecting?[/color]
>
> Code example:
>
> public delegate void DoSomething();
>
> public void countUpToaMillionOrSomething(DoSomething ThingToDo)
> {
> // call the "ThingToDo" asynchronously
> ThingToDo.BeginInvoke(null, null);
> }
>
>
> public void TargetOfInvocation()
> {
> Debug.WriteLine("Something.");
> }
>
>
> public void Test()
> {
> countUpToaMillionOrSomething(new DoSomething(TargetOfInvocation));
>
> // Give the method some time to execute before the Debugger detaches
> // (If you don't give it a long enough period of time, you may not see the
> output,
> // yet the "TargetOfInvocation" method will be invoked regardless)
> System.Threading.Thread.Sleep(1000);
> }
>
> --
> Dave Sexton
>
dave@www..jwaonline..com
> -----------------------------------------------------------------------
> "Grant" <gpsnett@hotmail.com> wrote in message
> news:eLbx4SjTFHA.2172@tk2msftngp13.phx.gbl...[color=green]
>> Yes thats right I need to understand how to pass a delegate to a new
>> thread I have created. I can do it synchronously but not asynchronously.
>> So in the example provided the 'BeginInvoke' command executes that on a
>> seperate thread using the threadpool, however Richard says:
>> ------
>> You example would be much more real world if the worker thread was
>> performing the work and then passing the requests to update the progress
>> bar back to the UI thread via control.Invoke (or BeginInvoke which is
>> preferable in my book)
>> ------
>>
>> That is really what I was after. I have a sepereate static class that
>> does all the work. I need this class to receive the delegate but I dont
>> know how to send it there on the thread I created, which Id like to
>> manage myself and not have it automatically done (I heard DoEvents was
>> evil in VB6, is it the same for .NET?) . Im starting up my own single
>> thread and not using the "threadpool waitcallback" way of creating
>> threads (havent learnt how to to do those just yet). So why does the IDE
>> tell me "Method name
>> expected" when I get to the following line of code:
>> thing.countUpToaMillionOrSomething(dlgate). What method name is it
>> expecting? I have created the delegate (which I understand is a wrapper
>> and points to the progress bar updater function I created on the main
>> form).
>>
>> Thanks for all your help,
>> Cheers,
>> Grant
>>
>>
>> "Dave" <NOSPAM-dave@dotcomdatasolutions.com> wrote in message
>> news:OuTvKffTFHA.2872@TK2MSFTNGP14.phx.gbl...[color=darkred]
>>> Lol. Thanks for the feedback, but does anyone read the initial question
>>> anymore??
>>>
>>>> Please could someone give me a simple exampe of how to get a delegate
>>>> passed to my worked class so that my main form can update its progress
>>>> bar?
>>>
>>> That's what he wanted. He needed to understand delegates, I assumed.
>>>
>>> Anyway... I think you missed the part where i check Form.RequiresInvoke,
>>> and if it is false, do the update directly.
>>> UpdateProgessCore is exactly what is sounds like... a method to update a
>>> progress bar. How do I know he's able to do this in one line of code?
>>> That's why it's a seperate method.
>>>
>>> Encapsulation.
>>>
>>> --
>>> Dave Sexton
>>>
dave@www..jwaonline..com
>>> -----------------------------------------------------------------------
>>> "Willy Denoyette [MVP]" <willy.denoyette@telenet.be> wrote in message
>>> news:eK1S$HdTFHA.3140@TK2MSFTNGP14.phx.gbl...
>>>> Is there something particular you are trying to prove here?
>>>> You run 'DoSomeWork' on the main UI thread, in 'DoSomeWork' you call an
>>>> asynchronous delegate to run 'UpdateProgress', as this one runs on a
>>>> thread from the pool you have to marshal the call to
>>>> 'UpdateProgressCore' (using the synchronous Invoke) so it runs on the
>>>> UI thread.
>>>> So basically, you are running a long task on the UI thread , call a
>>>> delegate to update the UI on another thread and then need to Invoke to
>>>> marshal the call to the UI is plain silly. No surprise you need to call
>>>> DoEvents.
>>>> Agreed, if you do not call DoEvents you'll consume all available pool
>>>> threads and crash (Invoke doesn't return as the messages don't get
>>>> dispatched) , but you shouldn't run the task on the UI thread in the
>>>> first place.
>>>>
>>>>
>>>> Willy.
>>>>
>>>>
>>>>
>>>>
>>>> "Dave" <NOSPAM-dave@dotcomdatasolutions.com> wrote in message
>>>> news:%23wx5HucTFHA.616@TK2MSFTNGP12.phx.gbl...
>>>>> Comment out Application.DoEvents and you'll see how it helps.
>>>>>
>>>>> Has to do with the fact that Windows uses a "Message Loop" so method
>>>>> invocations for WinForms controls aren't exactly "real-time". The
>>>>> message loop is like a queue, meaning first-in first-out. Your whole
>>>>> windows app depends on the messages from the queue reaching the main
>>>>> window procedure in order to process events, such as
>>>>> System.Windows.Forms.Form.Paint event. Without this message, the form
>>>>> will never refresh, and neither will it's child controls (i.e.
>>>>> progress bar). User actions are also messages, so the window would
>>>>> "freeze" up, not allowing you to interact with it, while the
>>>>> "DoSomeWork" method is executing on the main window thread.
>>>>>
>>>>> In other words:
>>>>> 1. Application.Run starts a message loop
>>>>> 2. Your Form (main application window) processes messages on the
>>>>> loop
>>>>> 3. My method (DoSomeWork) blocks the thread, not allowing it to
>>>>> accept messages while it is running
>>>>> 4. Application.DoEvents allows the Form to process messages
>>>>> currently in the queue, effectively updating the Form while DoSomeWork
>>>>> is doing some work :)
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Dave Sexton
>>>>>
dave@www..jwaonline..com
>>>>> -----------------------------------------------------------------------
>>>>> "Richard Blewett [DevelopMentor]" <richardb@NOSPAMdevelop.com> wrote
>>>>> in message news:uZys5gcTFHA.3952@TK2MSFTNGP15.phx.gbl...
>>>>>> That looks great - apart from I don't understand why you call
>>>>>> DoEvents - how does this help?
>>>>>>
>>>>>> Regards
>>>>>>
>>>>>> Richard Blewett - DevelopMentor
>>>>>>
http://www.dotnetconsult.co.uk/weblog
>>>>>>
>>>>>>
>>>>>>
>>>>>> nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<#mBN3FcTFHA.2420@TK2MSFTNGP12.phx.gbl>
>>>>>>
>>>>>> You don't need to use the Thread class to invoke the delegate
>>>>>> asynchronously, however, invoking it using BeginInvoke will execute
>>>>>> the method that the delegate points to on a ThreadPool thread. Also,
>>>>>> ProgressBar (and any other WinForms control) requires most of
>>>>>> its members to be executed/accessed on the thread that the control
>>>>>> was created on. To account for this requirement, a proper
>>>>>> example can't be too simple.
>>>>>>
>>>>>> Here's the simplest approach to updating a progress bar aynchronously
>>>>>> in a WinForms app (the proper way). I'm assuming that each
>>>>>> method is contained by a class derived from
>>>>>> System.Windows.Forms.Form:
>>>>>>
>>>>>> private delegate void UpdateProgressInvoker(int Position);
>>>>>> private System.Windows.Forms.ProgressBar progressBar;
>>>>>>
>>>>>> /// <summary>Test the progress bar asynchronous update code</summary>
>>>>>> public void DoSomeWork()
>>>>>> {
>>>>>> progressBar.Minimum = 0;
>>>>>> progressBar.Maximum = 100;
>>>>>>
>>>>>> for (int i = 0; i < 10000; i++)
>>>>>> {
>>>>>> // Create a pointer to the UpdateProgress method
>>>>>> UpdateProgressInvoker del = new
>>>>>> UpdateProgressInvoker(UpdateProgress);
>>>>>>
>>>>>> // Invoke the method asynchronously
>>>>>> del.BeginInvoke((int) (i / 100), null, null);
>>>>>>
>>>>>> // Tell the app to handle pending messages
>>>>>> // (so the form doesn't freeze and the progress bar is updated
>>>>>> visually)
>>>>>> Application.DoEvents();
>>>>>> }
>>>>>> }
>>>>>>
>>>>>>
>>>>>> /// <summary>
>>>>>> /// This method does not update the progress bar directly. Instead,
>>>>>> it ensures that the
>>>>>> /// <see cref="UpdateProgressCore" /> method (which actually does the
>>>>>> work) is executed on the
>>>>>> /// thread that the ProgressBar was created on.
>>>>>> /// </summary>
>>>>>> private void UpdateProgress(int Position)
>>>>>> {
>>>>>> // Check if the Form.InvokeRequired property is true. This will
>>>>>> indicate that
>>>>>> // the currently executing thread is not the thread that the
>>>>>> ProgressBar was created on.
>>>>>> // To update the progress bar synchronously, we will need to invoke
>>>>>> the method on the
>>>>>> // main thread.
>>>>>> // [this] must be a reference to a Form object.
>>>>>> if (!this.InvokeRequired)
>>>>>> {
>>>>>> // Create a pointer to the UpdateProgressCore method which performs
>>>>>> the actual update
>>>>>> UpdateProgressInvoker del = new
>>>>>> UpdateProgressInvoker(UpdateProgressCore);
>>>>>>
>>>>>> // Invoke the method asynchronously on the main thread of the
>>>>>> application.
>>>>>> // By using Form.Invoke, we ensure that our progress bar will be
>>>>>> updated properly.
>>>>>> this.Invoke(del, new object[] { Position });
>>>>>> }
>>>>>> else
>>>>>> // Currently executing thread is the ProgressBar's thread,
>>>>>> // so update the progress bar normally
>>>>>> UpdateProgressCore(Position);
>>>>>> }
>>>>>>
>>>>>> /// <summary>
>>>>>> /// Do not call this method directly. Instead, call <see
>>>>>> cref="UpdateProgress" />.
>>>>>> /// </summary>
>>>>>> private void UpdateProgressCore(int Position)
>>>>>> {
>>>>>> progressBar.Value = Position;
>>>>>> }
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Dave Sexton
>>>>>>
dave@www..jwaonline..com
>>>>>> -----------------------------------------------------------------------
>>>>>> "Grant" <gpsnett@hotmail.com> wrote in message
>>>>>> news:Oo0nRtaTFHA.3840@tk2msftngp13.phx.gbl...
>>>>>> >I am having great difficulty understanding this and any code samples
>>>>>> >I find online are kilometres long and complicated to
>>>>>> >understand...Please could someone give me a simple exampe of how to
>>>>>> >get a delegate passed to my worked class so that my main form
>>>>>> >can update its progress bar? I know it has something to do with
>>>>>> >begininvoke and endinvoke etc, but I just need a simple sample to
>>>>>> >understand the convention.
>>>>>> >
>>>>>> >
>>>>>> > Code from my main form:
>>>>>> > -----------------------------------
>>>>>> > form1Delegate dlgate = new form1Delegate(IncreaseProgressBar);
>>>>>> > //thing.countUpToaMillionOrSomething(new
>>>>>> > form1Delegate(this.IncreaseProgressBar));
>>>>>> > Thread thread = new Thread(new
>>>>>> > ThreadStart(thing.countUpToaMillionOrSomething(dlg ate)));
>>>>>> > thread.Start();
>>>>>> > -----------------------------------
>>>>>> >
>>>>>> > Code from my worker class called 'thing'
>>>>>> > -----------------------------------
>>>>>> > public static void countUpToaMillionOrSomething(Form1.form1Delegate
>>>>>> > myMethodDelegate)
>>>>>> > {
>>>>>> > int x = 0;
>>>>>> > while ( x < 50)
>>>>>> > {
>>>>>> > Thread.Sleep(70);
>>>>>> > x ++ ;
>>>>>> > myMethodDelegate();
>>>>>> > }
>>>>>> > }
>>>>>> > -----------------------------------
>>>>>> >
>>>>>> >
>>>>>> > I can only get it to work synchronously with the following line:
>>>>>> >
>>>>>> > thing.countUpToaMillionOrSomething(new
>>>>>> > form1Delegate(this.IncreaseProgressBar));
>>>>>> >
>>>>>> > If I try compile with the thread example above it spews about
>>>>>> > 'Method name expected' and underlines the following bit of code:
>>>>>> >
>>>>>> > thing.countUpToaMillionOrSomething(dlgate)
>>>>>> >
>>>>>> > Any help greatly appreciated,
>>>>>> > Thanks,
>>>>>> > Grant
>>>>>> >
>>>>>> >
>>>>>>
>>>>>>
>>>>>>
>>>>>> [microsoft.public.dotnet.languages.csharp]
>>>>>
>>>>>
>>>>
>>>>
>>>
>>>[/color]
>>
>>[/color]
>
>[/color]