Search code examples
c#wpfmultithreadinginvokedispatcher

Begin Invoke is not running


Im using System.Windows.Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() => ... for a wpf graphic refresh.

It works in my other function greatfully, but in my SQL delete function it wount be triggered/executed.

I tried it with System.Windows.Forms.Application.DoEvents(); but it wount do anything.

Set_Loading_Changed()
{
    System.Windows.Application.Current.Dispatcher.BeginInvoke(
        DispatcherPriority.Input, 
        new Action(() =>
        {
            if (BLoading)
            {
                DataGrid_Anzeige.IsEnabled = false;

                Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
            }
            else
            {
                DataGrid_Anzeige.IsEnabled = true;
        
                Mouse.OverrideCursor = null;
            }
        }));
}
Btn_Remove()
{
    ...
    Set_Loading_Changed();

    using (OleDbConnection ODC = new OleDbConnection("..."))
    {
        foreach (var selectedRow in DataGrid_Anzeige.SelectedItems.OfType<DataRowView>())
        {
            sSQL_Statement = "...";

            ODC.Open();
            OleDbCommand ODCmd = new OleDbCommand(sSQL_Statement, ODC);

            ODCmd.ExecuteNonQuery();
            ODC.Close();

EDIT:

I insert the complete part of my Set_Load_Changed() function, hope you can get a clue with this informations.

Im using it primarly in my search Thread (Task.Factory.StartNew(() => { ... }));) so it must be the DispatcherPriority.Input.


Solution

  • To change the cursor in WPF is unfortunately not as straightforward as in WinForms. I remember struggling with it myself until I stumbled upon the following solution. I didn't come up with this myself, I'll try and find the source to give credit where it is due.

    using System;
    using System.Collections.Generic;
    using System.Windows.Input;
    
    namespace MyNamespace
    {
        public class OverrideCursor : IDisposable
        {
            static Stack<Cursor> s_Stack = new Stack<Cursor>();
    
            public OverrideCursor(Cursor changeToCursor = null)
            {
                if (changeToCursor == null)
                    changeToCursor = Cursors.Wait;
    
                s_Stack.Push(changeToCursor);
    
                if (Mouse.OverrideCursor != changeToCursor)
                    Mouse.OverrideCursor = changeToCursor;
            }
    
            public void Dispose()
            {
                s_Stack.Pop();
                var cursor = _stack.Count > 0 ? _stack.Peek() : null;
                if (Mouse.OverrideCursor != cursor)
                    Mouse.OverrideCursor = cursor;
    
            }
        }
    }
    

    Now this disposable class can be used anywhere in your project to change the cursor temporarily.

    using (new OverrideCursor())
    {
        //your code 
    }
    

    This will change the cursor to anything you want by passing the cursor as parameter of the constructor, or nothing to use Cursors.Wait by default. For the time needed to execute any code placed inside the using-block the cursor will be changed turning back to normal afterwards.
    You can also initiate an object of the class without the using-block to set it indefinitely but you shouldn't forget to call Dispose() when done.

    Edit: source: https://stackoverflow.com/a/675686/4579864