开始调用不是 运行
Begin Invoke is not running
我正在使用 System.Windows.Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() => ...
进行 wpf 图形刷新。
它在我的其他功能中非常有效,但在我的 SQL 删除功能中它不会是 triggered/executed。
我用 System.Windows.Forms.Application.DoEvents();
试过了,但它什么也做不了。
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();
编辑:
我插入了我的 Set_Load_Changed()
函数的完整部分,希望您能从这些信息中得到线索。
我主要在我的搜索主题 (Task.Factory.StartNew(() => { ... }));
) 中使用它,所以它一定是 DispatcherPriority.Input
。
如果想在 Set_Loading_Changed()
连接到数据库之前执行任何操作,您应该调用 Invoke
而不是 BeginInvoke
:
Set_Loading_Changed()
{
System.Windows.Application.Current.Dispatcher.Invoke(...);
}
What's the difference between Invoke() and BeginInvoke()
您 运行 陷入了误解 WPF 线程系统的常见问题。 WPF 的结构方式是一个线程用于程序 运行 并修改 UI 中的,通常称为 UI 线程,以及您没有正常使用方式的第二个线程,它会自动呈现 UI,通常称为呈现或合成线程。
这里你需要知道的关键点是,如果你在 BeginInvoke()
之后立即用大型操作(如数据库读取或大型计算)停止 UI 线程,那么你将阻止 UI 线程从 运行 执行这些命令,直到您允许它调用下一个操作。 BeginInvoke()
只是将下一次允许调度程序执行的操作排队 - 调度程序不会中断当前正在执行的操作。将优先级设置为 Input
可确保它在其他优先级较低的工作之前得到处理,但仍不会导致它中断您当前的方法。
如果您改为调用 Invoke()
,您将中断工作以要求调度员执行操作,然后 return 完成后您正在做的事情。
虽然这比您当前获得的行为更可取,但这不是您打算使用调度程序的方式,并且仍然会导致您的应用在完成长时间后显示 'frozen'手术。为避免这种情况,最简单的做法是 运行 任务中的长操作,使用 async/await 关键字和任务并行库。
Stephen Cleary 有一个很棒的博客,其中涵盖了很多与此相关的主题。他的介绍post(追溯到关键字的介绍)是 here。
如果您在这方面有更多问题,我鼓励您浏览他的博客 - 他是解释该领域的主要专家之一,并且涵盖了您 运行 遇到的大部分问题。
进一步阅读:
What's the difference between Invoke() and BeginInvoke()?
WPF Threading Model
不幸的是,在 WPF 中更改光标不像在 WinForms 中那样简单。我记得自己一直在努力解决这个问题,直到我偶然发现了以下解决方案。这不是我自己想出来的,我会尝试找到来源以在应有的地方给予信任。
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;
}
}
}
现在这个一次性 class 可以在项目的任何地方使用来临时更改光标。
using (new OverrideCursor())
{
//your code
}
通过将光标作为构造函数的参数传递,这会将光标更改为您想要的任何内容,或者默认情况下不使用 Cursors.Wait
。
对于执行 using 块内的任何代码所需的时间,光标将被更改,然后恢复正常。
您也可以在没有使用块的情况下启动 class 的对象来无限期地设置它,但是您不应该忘记在完成后调用 Dispose()
。
编辑: 来源:
我正在使用 System.Windows.Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() => ...
进行 wpf 图形刷新。
它在我的其他功能中非常有效,但在我的 SQL 删除功能中它不会是 triggered/executed。
我用 System.Windows.Forms.Application.DoEvents();
试过了,但它什么也做不了。
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();
编辑:
我插入了我的 Set_Load_Changed()
函数的完整部分,希望您能从这些信息中得到线索。
我主要在我的搜索主题 (Task.Factory.StartNew(() => { ... }));
) 中使用它,所以它一定是 DispatcherPriority.Input
。
如果想在 Set_Loading_Changed()
连接到数据库之前执行任何操作,您应该调用 Invoke
而不是 BeginInvoke
:
Set_Loading_Changed()
{
System.Windows.Application.Current.Dispatcher.Invoke(...);
}
What's the difference between Invoke() and BeginInvoke()
您 运行 陷入了误解 WPF 线程系统的常见问题。 WPF 的结构方式是一个线程用于程序 运行 并修改 UI 中的,通常称为 UI 线程,以及您没有正常使用方式的第二个线程,它会自动呈现 UI,通常称为呈现或合成线程。
这里你需要知道的关键点是,如果你在 BeginInvoke()
之后立即用大型操作(如数据库读取或大型计算)停止 UI 线程,那么你将阻止 UI 线程从 运行 执行这些命令,直到您允许它调用下一个操作。 BeginInvoke()
只是将下一次允许调度程序执行的操作排队 - 调度程序不会中断当前正在执行的操作。将优先级设置为 Input
可确保它在其他优先级较低的工作之前得到处理,但仍不会导致它中断您当前的方法。
如果您改为调用 Invoke()
,您将中断工作以要求调度员执行操作,然后 return 完成后您正在做的事情。
虽然这比您当前获得的行为更可取,但这不是您打算使用调度程序的方式,并且仍然会导致您的应用在完成长时间后显示 'frozen'手术。为避免这种情况,最简单的做法是 运行 任务中的长操作,使用 async/await 关键字和任务并行库。
Stephen Cleary 有一个很棒的博客,其中涵盖了很多与此相关的主题。他的介绍post(追溯到关键字的介绍)是 here。
如果您在这方面有更多问题,我鼓励您浏览他的博客 - 他是解释该领域的主要专家之一,并且涵盖了您 运行 遇到的大部分问题。
进一步阅读:
What's the difference between Invoke() and BeginInvoke()?
WPF Threading Model
不幸的是,在 WPF 中更改光标不像在 WinForms 中那样简单。我记得自己一直在努力解决这个问题,直到我偶然发现了以下解决方案。这不是我自己想出来的,我会尝试找到来源以在应有的地方给予信任。
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;
}
}
}
现在这个一次性 class 可以在项目的任何地方使用来临时更改光标。
using (new OverrideCursor())
{
//your code
}
通过将光标作为构造函数的参数传递,这会将光标更改为您想要的任何内容,或者默认情况下不使用 Cursors.Wait
。
对于执行 using 块内的任何代码所需的时间,光标将被更改,然后恢复正常。
您也可以在没有使用块的情况下启动 class 的对象来无限期地设置它,但是您不应该忘记在完成后调用 Dispose()
。
编辑: 来源: