fbpx
Welcome, Guest
Username: Password: Remember me
  • Page:
  • 1

TOPIC: update UI in Task?

update UI in Task? 1 year 3 months ago #4295

  SHirsch's Avatar Topic Author SHirsch Offline Posts: 110
Hi all,

source is following code:
SELF:obtnInstallService:Enabled := FALSE
AWAIT Task.Run(Action{{ => 
   VAR helper := WindowsServiceHelper{}
   helper:InstallService()
   SELF:CheckButtons()
}})

In another thread there was a suggestion to move CheckButtons (update of UI, with checking InvokeRequired) after AWAIT because 'It's generally better to avoid updating the UI thread from inside a task.' (by Nick).
My questions:
1. Why (is better to avoid...)?
2. How should progressbar update be done in long running task?

Regards,
Stefan

Please Log in or Create an account to join the conversation.

update UI in Task? 1 year 3 months ago #4302

  NickFriend's Avatar NickFriend Offline Posts: 193
Hi Stefan,

As to why, I'm sure Robert or Chris can give a better answer than me, but I think the basic idea is that when you start a task it runs on a separate thread from the UI. If you then carry out processes that directly affect the UI, then you're literally crossing your threads!... anyway you get the idea ;)

To update the UI thread, you need to use a TaskScheduler. In pseudo code (C# as I'm not reliable in X#)
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
await Task.Factory.StartNew(()=> { MyMethod(uiScheduler, otherparams...); });

private void MyMethod(TaskScheduler uiScheduler, otherparams...)
{
    do stuff....

    // update the UI
    Task.Factory.StartNew(()=>
    {
       // from here you can now safely access any methods or properties affecting the ui
    }, CancellationToken.None, TaskCreationOptions.None, uiScheduler);

    continuing doing more stuff
}

HTH

Nick

Please Log in or Create an account to join the conversation.

update UI in Task? 1 year 3 months ago #4305

  ic2's Avatar ic2 Offline Posts: 499
I would also like to add the so called non recommended way to do this. Not sure why it's not recommended, usually that it not explained, as it works fine. Nick's method certainly works 'by the book' but you need to 'await' all your methods to use it.

Dick

this.UpdateProgressBar(1);
ExtensionMethods.ProcessUITasks();

public static void ProcessUITasks()
// When called, forces the UI to redraw.
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(delegate (object parameter) {
frame.Continue = false;
return null;
}), null);
Dispatcher.PushFrame(frame);
}

Please Log in or Create an account to join the conversation.

update UI in Task? 1 year 3 months ago #4307

  wriedmann's Avatar wriedmann Away Posts: 1573
Hello,

AFAIK there is BackgroundWorker class ( https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.110).aspx ) for operations on a separate thread, usable for WPF applications.

It can be used as follows:
_oWorker := BackgroundWorker{}
_oWorker:WorkerReportsProgress := true
_oWorker:WorkerSupportsCancellation := true
_oWorker:DoWork += ExecuteProcessAsync
_oWorker:ProgressChanged += ProgressProcessAsync
_oWorker:RunWorkerCompleted += CompletedProcessAsync
_oWorker:RunWorkerAsync()

method ProgressProcessAsync( oSender as object, e as ProgressChangedEventArgs ) as void
	
_oProgress:Text	:= ( string ) e:UserState
	
return   

method CompletedProcessAsync( oSender as object, e as RunWorkerCompletedEventArgs ) as void	

_oProgress:Text	:= ( string ) e:UserState
_oWorker := null                            
	
return  

method ExecuteProcessAsync( oSender as object, e as DoWorkEventArgs ) as void
local oProcess as AsyncProcess
	
oProcess := AsyncProcess{ _oWorker }
oProcess:Process()
	
return

I have also done a sample in X#/WPF - I've attached a XIDE export file of a complete sample of it.
Or you can look here:

https://www.dotnetperls.com/backgroundworker

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it
Attachments:

Please Log in or Create an account to join the conversation.

update UI in Task? 1 year 3 months ago #4310

  NickFriend's Avatar NickFriend Offline Posts: 193
Hi Dick,

The code you posted is a way of forcing the UI to update when you've blocked it by some long-running process, it has nothing to do with async programming or await. The whole point of asynchronous programming is to avoid blocking the UI in the first place. This is what task-based async is all about.

I've used all three proposed methods - in fact I think I gave you that ProcessUITasks code way back in the Vulcan ng days, before I knew better ;-)- and I can categorically state that task based is the way to go for async. It results in very clear code, which is very important if you apply async programming large scale, and it works 100%.

BackgroundWorker as illustrated by Wolfgang will work, but it results in much more convoluted code (though I'm sure Wolfgang will disagree!).

Nick

Please Log in or Create an account to join the conversation.

update UI in Task? 1 year 3 months ago #4311

  hsc's Avatar hsc Offline Posts: 96
Hi Wolfgang,

My English is not very good but I will try to formulate my question.
I want to ask what is the best solution.
The client runs an app and works in it. While running an app, I need to track the partition of the database where a new table appears. If it appears, add it to another table and it will be deleted. This will happen several times during app launch.
The question is what to use - bacgroudworker in the application or write another program as a system service?

Juraj

Please Log in or Create an account to join the conversation.

update UI in Task? 1 year 3 months ago #4313

  SHirsch's Avatar Topic Author SHirsch Offline Posts: 110
Hi all,

in the current project I'm using Windows.Forms. So complete call looks like this:
PRIVATE METHOD CheckButtons() AS VOID
    IF SELF:InvokeRequired == TRUE
        SELF:BeginInvoke(Action{CheckButtons})
        RETURN
    ENDIF
    //savely executed UI Code
RETURN 
So it doesn't matter from which task or thread the method is called it's always executed savely.

In WPF I have following code that is called from tasks or threads:
void runCopyFileEvent(CopyInfo cpi)
{
   this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
         new UpdateProgressBarDelegate(UpdateProgressBar), cpi);
}

This way I do not have to implement UI update handling in every task or thread. Just call the method inside the task and everything else is handled in UI class. OK, the method is not called directly from threads, here I use delegates. Advantage in my opinion is that the code of the thread is independable of UI framework.

Any drawbacks?

Regards,
Stefan

Please Log in or Create an account to join the conversation.

update UI in Task? 1 year 3 months ago #4314

  wriedmann's Avatar wriedmann Away Posts: 1573
Hi Juraj,

I would do that definitely in a separate Windows service. It is a separate work that has nothing to do with the currently running application.

If you need a sample for a Windows service, I can give you one.

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

update UI in Task? 1 year 3 months ago #4315

  ic2's Avatar ic2 Offline Posts: 499
Hello Nick,

The whole point of asynchronous programming is to avoid blocking the UI in the first place. This is what task-based async is all about.

I've used all three proposed methods - in fact I think I gave you that ProcessUITasks code way back in the Vulcan ng days, before I knew better ;-)- and I can categorically state that task based is the way to go for async. It results in very clear code, which is very important if you apply async programming large scale, and it works 100%.


I agree with you and as I wrote, the code you gave here (and earlier to me) works. But the program needs to be async all over for it to work. I've applied the code I gave in a program which was not async and that code also works 100%.

I do not consider it less readable, actually on the contrary: I just add one line of code after the update of the progress bar and it remains visible. Like with the VO ApplcationExecWhileEvent() which worked even better because you only had to issue it once.

I must add that I consider it pretty poor that in .Net there is something like a progress bar but when applied it simply doesn't work. Until you transform your program to a fully separated set of tasks, or have it followed by the "ProcessUITasks" task method. If .Net was well designed a programmer shouldn't have to worry about how it works, as long as it works 'out of the box'. I always thought that was the whole idea of .Net but the more I work with it the more I methods and namespaces I see which do not work without a lot of extra research and programming.

Dick

Please Log in or Create an account to join the conversation.

update UI in Task? 1 year 3 months ago #4316

  NickFriend's Avatar NickFriend Offline Posts: 193

Dick wrote: I do not consider it less readable

Hi Dick,

Re. the readability, I was referring to BackgroundWorker which is a valid alternative for async programming.

Anyway, I was giving an opinion over the general approach to async and Stefan obviously has different requirements, and an approach which I'm not qualified to comment on.

Nick

Please Log in or Create an account to join the conversation.

update UI in Task? 1 year 3 months ago #4317

  hsc's Avatar hsc Offline Posts: 96
Hi Wolfgang,

Thank you for your response. Any service sample would help me. My mail - "This email address is being protected from spambots. You need JavaScript enabled to view it."

Juraj

Please Log in or Create an account to join the conversation.

update UI in Task? 1 year 3 months ago #4319

  wriedmann's Avatar wriedmann Away Posts: 1573
Hi Juraj,

you can find a sample here:

https://www.riedmann.it/download/VulcanService.viaef

It is a XIDE export file.

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

  • Page:
  • 1