简体   繁体   中英

Kill async task c#, wpf

In my application i have class PrimaryViewModel (abstract) and every ViewModel inherit from it. To get data every X seconds i have written following virtual method

 protected virtual async void RunSynchronizeTask()
    {
        await Task.Run(() =>
        {
            while (true)
            {
                Thread.Sleep(RefreshTime);
                if (DateTime.Now.TimeOfDay - LastSyncrhonization.TimeOfDay > RefreshTime)
                {
                    Application.Current.Dispatcher.Invoke(delegate
                    {
                        GetDataAndRefreshUI();
                    });
                    LastSyncrhonization = DateTime.Now;
                }
            }
        });
    }

So every viewModel has it owns method and it own task which will get data from DB and refresh binded controls (for example messageViewModel refresh messages list every 0.5 seconds)

but problem is that when i run released application (no debug mode, just build as release and open exe) and close, the app will close, but this async task is still working (i see it in task manager)

What should i do? How to assign this task to something, i cannot do : var task = await.Task.Run(...)

If i could i would create some static list with referencses to theses tasks and on application close i would kill them or sth...

You go from an async void to a Task.Run() , which is doubling up.
And then you do the actual work in a Dispatcher.Invoke()

The only thing that is truly async (concurrent) here is the Thread.Sleep() .

So you can replace all this with a DispatcherTimer. That should cure your halting problem too.

Thanks Fabian! works great with cancellation token :

  protected virtual async void RunSynchronizeTask()
        {
            var cancelationToken = new CancellationToken();
            App.TaskToDisposeTokens.Add(cancelationToken);
            await Task.Run(() =>
            {
                try { 
                while (true)
                {
                    Thread.Sleep(RefreshTime);
                    if (DateTime.Now.TimeOfDay - LastSyncrhonization.TimeOfDay > RefreshTime)
                    {
                        Application.Current.Dispatcher.Invoke(delegate
                        {
                            GetDataAndRefreshUI();
                        });
                        LastSyncrhonization = DateTime.Now;
                    }
                }
                }
                catch(OperationCanceledException) { }
            }, cancelationToken);

        }

App.Cs

 private void Application_Exit(object sender, ExitEventArgs e)
        {
            foreach(var token in TaskToDisposeTokens)
            {
                token.ThrowIfCancellationRequested();
            }
        }

and in App.Xaml

<Application x:Class="RandevouWpfClient.App"
           ...
             Exit="Application_Exit">

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM