Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
297 views
in Technique[技术] by (71.8m points)

c# - Custom Busy overlay on WPF WizardControl using async await

I need load a overlay on a WPF wizardcontrol. I am using a busyIndicator tool from the wpf extended tooklit.

The code for async await works but the gui thread locks . I am trying add a please wait message when the await calls the function

private async void Button1_Click(object sender, RoutedEventArgs e)
        {
         BusyIndicator.IsBusy = true;
         BusyIndicator.IsEnabled = true;
         BusyIndicator.BusyContent = "Please wait while Site is provisioned";

                            await Task.Run(() =>
                           {
                              LongRunningFunction();
                           });

         BusyIndicator.IsBusy=false;
        }

The XAML for the BusyIndicator is as below.

<xctk:BusyIndicator x:Name="BusyIndicator" IsBusy="False"  BusyContent="Please Wait">

</xctk:BusyIndicator>

The LonRunningFunction is a Webservice call which does not update the UI only returns a Bool value

public static bool LongRunningFunction(string URL)
        {

            bool IsPresent = CallWebservice()
           return IsPresent;
        }

Issue

1) The BusyIndicator does not seem to fire before the async call instead it seems to be fire when the LongRunning task completes

2) What is the correct process to call a gui overlay when async and await is used.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is the way I tackled the problem with asynchronous calls.
Context:
Here I am using MvvM to show you good practice when working with WPF

using System.Threading;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Threading;
class VM
    {
        Dispatcher _dispatcher = Dispatcher.CurrentDispatcher;
        //Time consuming operation
        private void LongTask()
        {
            Thread.Sleep(5000);
            //in here if you need to send something to the UI thread like an event use it like so:
            _dispatcher.Invoke(new Action(() =>
            {
                //some code here to invoke an event
                if (ComponentsLoaded != null)
                    ComponentsLoaded(this, new EventArgs { });
            }));
        }

        private ICommand _command;
        //This is the command to be used instead of click event handler
        public ICommand Command
        {
            get { return _command; }
            private set { _command = value; }
        }
        //method associated with ICommand
        void commandMethod(object parameter)
        {
            Busy = true;
            ThreadPool.QueueUserWorkItem(new WaitCallback(multiThreadTask));
            Busy = false;
        }
        //the task to be started on another thread
        void multiThreadTask(object parameter)
        {
            LongTask();
        }

        public event EventHandler ComponentsLoaded;
    }  

This is what I use when working with multiple threads in WPF.
You can still use this in the code-behind just instantiate the Dispatcher and you're good to go.
If you need any more info just let us know. HTH


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...