我对跨线程访问遇到的场景感到困惑.这是我想要做的:
主UI线程 - 菜单项单击我创建后台工作程序并异步运行它
private void actionSubMenuItem_Click(object sender, EventArgs e)
{
ToolStripMenuItem itemSelected = (ToolStripMenuItem)sender;
ExecuteTheActionSelected(itemSelected.Text);
}
Run Code Online (Sandbox Code Playgroud)
方法ExecuteTheActionSelected如下:
private void ExecuteTheActionSelected(string actionSelected)
{
BackgroundWorker localBackgroundWorker = new BackgroundWorker();
localBackgroundWorker.DoWork += new DoWorkEventHandler(localBackgroundWorker_DoWork);
localBackgroundWorker.RunWorkerAsync(SynchronizationContext.Current);
}
Run Code Online (Sandbox Code Playgroud)
该localBackgroundWorker_DoWork有:
ActionExecutionHelper actionExecutioner = new ActionExecutionHelper()
actionExecutioner.Execute();
Run Code Online (Sandbox Code Playgroud)
的Execute在于类具有INFACT调用在UI线程的事件处理方法调用方法:
public void Execute()
{
// ---- CODE -----
new MethodInvoker(ReadStdOut).BeginInvoke(null, null);
}
protected virtual void ReadStdOut()
{
string str;
while ((str = executionProcess.StandardOutput.ReadLine()) != null)
{
object sender = new object();
DataReceivedEventArgs …Run Code Online (Sandbox Code Playgroud) 在我的应用程序中,我有一个负责所有数据库操作的类.它从主类调用,并在动作完成后使用委托调用方法.因为它是异步的,我必须在我的GUI上使用invoke,所以我创建了一个简单的扩展方法:
public static void InvokeIfRequired<T>(this T c, Action<T> action)
where T: Control
{
if (c.InvokeRequired)
{
c.Invoke(new Action(() => action(c)));
}
else
{
action(c);
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试在textBox上调用它时,这工作正常:
textBox1.InvokeIfRequired(c => { c.Text = "it works!"; });
Run Code Online (Sandbox Code Playgroud)
但是当我尝试在ToolStripStatusLabel或ToolStripProgressBar上调用它时,我收到一个错误:
类型'System.Windows.Forms.ToolStripStatusLabel'不能在泛型类型或方法'SimpleApp.Helpers.InvokeIfRequired(T,System.Action)'中用作类型参数'T'.没有从'System.Windows.Forms.ToolStripStatusLabel'到'System.Windows.Forms.Control'的隐式引用转换.
我知道这可能是一个简单的修复,但我只能处理它:/
我一直在寻找这个问题的答案,但似乎找不到令人满意的答案。也许有人可以启发我。
我有一个后代,BindingList<T>用于存储对SynchronizationContext对象的引用,以在UI线程上引发其更改的事件。
现在,也有可能BindingList<T>在UI线程而不是后台线程上创建和使用它。没有InvokeRequired可用的财产该如何检查?调用SynchronizationContext.SendUI线程会有什么后果?
c# multithreading invokerequired winforms synchronizationcontext
我一直看到/使用代码的某种形式或方式:
public void method1(Object sender, EventArgs args)
{
if(dataGridView1.InvokeRequired)
dataGridView1.Invoke(new EventHandler(method1), null);
else
// Do something to dataGridView1
}
Run Code Online (Sandbox Code Playgroud)
我的问题是......当我使用时,GUI线程会发生什么Invoke?它是否像一个中断,线程将立即执行method1?
那里.我正在使用C#.wpf,我从C#source获得了一些代码,但我无法使用它.有什么我必须改变的吗?或者呢?
// Delegates to enable async calls for setting controls properties
private delegate void SetTextCallback(System.Windows.Controls.TextBox control, string text);
// Thread safe updating of control's text property
private void SetText(System.Windows.Controls.TextBox control, string text)
{
if (control.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
Invoke(d, new object[] { control, text });
}
else
{
control.Text = text;
}
}
Run Code Online (Sandbox Code Playgroud)
如上面的代码,错误在InvokeRequired和Invoke
目的是,我有一个内容的文本框,将为每个进程递增.
这是文本框的代码. SetText(currentIterationBox.Text = iteration.ToString());
代码有什么问题吗?
感谢您的任何帮助
编辑
// Delegates to enable async calls for setting controls properties
private delegate …Run Code Online (Sandbox Code Playgroud) 当我想在Windows窗体工作时使用委托类进行调用时,我总是必须使用InvokeRequired.没关系.但是谁在工作时更改了InvokeReuqired属性.请检查此图片:

我在执行InvokeRequired时遇到stackverflow错误.
System.StackOverflowException未处理

怎么解决?没有信息我查看详细信息.
固定版本:
public DialogResult ShowMessage(string msg, string caption, MessageBoxButtons buttons)
{
if (InvokeRequired)
{
Func<DialogResult> m = () => MessageBox.Show(msg, caption, buttons);
return (DialogResult)Invoke(m);
}
else
{
return MessageBox.Show(msg, caption, buttons);
}
}
Run Code Online (Sandbox Code Playgroud) 我知道,这可能是一个非常简单的问题,但我无法确定.我在一个模块中有这个:
Public theHandle As IntPtr
Run Code Online (Sandbox Code Playgroud)
这在我的主要形式名为Form1:
Private Sub Form1_HandleCreated(sender As Object, e As System.EventArgs) Handles Me.HandleCreated
theHandle = Me.Handle
End Sub
Run Code Online (Sandbox Code Playgroud)
我有许多其他类,模块和线程,没有使用InvokeRequired,我使用它来从任何地方调用代理.我的意思是来自其他线程,类,模块等.
DirectCast(Form1.FromHandle(theHandle), Form1).Invoke(D_Calculate)
Run Code Online (Sandbox Code Playgroud)
代替:
D_Calculate.Invoke()
Run Code Online (Sandbox Code Playgroud)
这是一种不好的做法吗?是否真的有InvokeRequired每次检查的目的?
我有一个"调用"问题,我无法解决.我会尽量在我的描述中尽可能彻底,但我是新手,所以请耐心等待,如果您需要更多信息,请告诉我.
我有一个运行后台线程,当提示时将禁用主线程上创建的表单上的一堆复选框.为了做到这一点,我需要使用invoke和委托安全地交叉线程,但我必须做错了.最重要的是,当我在调试器中检查这个时,我看到它会在代码的ACTION部分运行两次InvokeRequired.我可以通过用一个包围ACTION来解决这个问题else,虽然它不会运行else两次,但仍然会尝试再次通过该方法.
delegate void ManualCurtainShuttoffHandler();
public void ManualCurtainShutoff()
{
if (InvokeRequired)
{
Invoke(new ManualCurtainShuttoffHandler(ManualCurtainShutoff));
}
// ACTION: Disable check boxes
}
Run Code Online (Sandbox Code Playgroud)
我只想知道为什么它会两次运行该方法.如果您需要更多信息,请告诉我,我很乐意与您分享.
invokerequired ×10
c# ×8
.net ×4
winforms ×4
invoke ×3
delegates ×2
.net-3.5 ×1
begininvoke ×1
vb.net ×1
wpf ×1