.net 如何从WPF中的另一个线程读取textbox.Text值?
在我的WPF表单中,我有一个文本框。.net 如何从WPF中的另一个线程读取textbox.Text值?,.net,wpf,multithreading,.net,Wpf,Multithreading,在我的WPF表单中,我有一个文本框。 计时器过期时,需要提取文本框的内容。 计时器运行在与UI不同的线程中 问题有两个方面: 从GUI线程跨线程读取值的最简单、最可读的方法是什么(我发现了几种,它们看起来太冗长了,不适合真正基本的东西) 我不能以非阻塞方式阅读课文吗?在这种情况下,我不关心线程安全 --编辑-- 我使用了Dispatcher,但有一个比它更详细的调用: 不过我不介意说得再简短些。访问文本属性应该是非常基本的。从创建GUI对象的线程以外的线程读取GUI对象的值没有“快速破解”的
计时器过期时,需要提取文本框的内容。
计时器运行在与UI不同的线程中 问题有两个方面:
- 从GUI线程跨线程读取值的最简单、最可读的方法是什么(我发现了几种,它们看起来太冗长了,不适合真正基本的东西)
- 我不能以非阻塞方式阅读课文吗?在这种情况下,我不关心线程安全
我使用了Dispatcher,但有一个比它更详细的调用: 不过我不介意说得再简短些。访问文本属性应该是非常基本的。从创建GUI对象的线程以外的线程读取GUI对象的值没有“快速破解”的方法。WPF不会允许你做所有的事情。Windows窗体有时会抱怨,但WPF要严格得多 您需要了解调度程序。这可能看起来很冗长,但其实并不难理解。您将一个委托传递给调度程序,该调度程序指向您希望在GUI线程上调用的方法,并且它会这样做 下面是一个很好的简单示例:
奥辛是对的,你需要看看。这样的方法应该可以,而且不会太冗长:
System.Windows.Application.Current.Dispatcher.Invoke(
DispatcherPriority.Normal,
(ThreadStart)delegate { text = MyTextBox.Text; });
您可以:
- 使用调度消息以从后台线程在UI线程上执行。一次
将使您获得尽可能快的响应发送
- 使用来定期在UI线程上执行消息
- 使用
绑定将OneWayToSource
属性连接到后台组件上的属性。这样,您就不必做任何工作来获取属性值——它已经提供给您的组件Text
- 我的解决方案。。。
XAML:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<TextBox Height="23" Margin="28,27,130,0" Name="textBox1" VerticalAlignment="Top" />
<Button Height="23" HorizontalAlignment="Left" Margin="28,56,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click">Button</Button>
<TextBox Margin="34,85,12,54" Name="textBox2" />
</Grid>
按钮
和cs文件:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
new System.Threading.Thread(this.Cuenta).Start();
}
private void Cuenta()
{
for (int i = 0; i < 100000; i++)
this.SetValues(string.Format("Counting... {0} ", i));
}
private void SetValues(string str)
{
System.Windows.Application.Current.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
(System.Threading.ThreadStart)delegate { textBox1.Text = str; });
}
}
公共部分类窗口1:窗口
{
公共窗口1()
{
初始化组件();
}
私有无效按钮1\u单击(对象发送者,路由目标)
{
新系统.Threading.Thread(this.Cuenta.Start();
}
私人void Cuenta()
{
对于(int i=0;i<100000;i++)
SetValues(string.Format(“Counting…{0}”,i));
}
私有void集合值(字符串str)
{
System.Windows.Application.Current.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
(System.Threading.ThreadStart)委托{textBox1.Text=str;});
}
}
第二个文本框用于线程运行时的类型测试,另一个答案是使用Jeff Wilcox的SmartDispatcher类 在构造函数或加载事件中的某个位置执行SmartDispatcher.Initialize()(设置UI调度程序) 然后,在需要设置属性或调用方法的任何位置:
Action a = delegate { <statements> };
SmartDispatcher.BeginInvoke(a);
动作a=委托{};
SmartDispatcher.BeginInvoke(a);
这样做的好处是,您不需要知道它是否在UI线程上(并且您可能需要从这两个线程中都知道)。如有必要,SmartDispatcher会处理线程开关
以上内容是异步的,但如果需要同步,只需添加另一个方法来调用Invoke,而不是BeginInvoke。只是碰巧进入了这里。不久前,我刚刚开始构建一个静态类,我可以将它添加到我的项目中,以便快速访问一些常见的控件属性。随着时间的推移,它会变得臃肿,但在隐藏大量调度程序代码的同时使事情变得非常简单。粗糙但有效。可能会给你一些想法。 我基本上可以这样做:
string temp = SafeGuiWpf.GetText(originalTextBox);
如果您觉得SafeGuiWpf有帮助的话,下面是它上次的样子。(认为它在NET3及以上版本中有效,但已经有一段时间了)
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Controls.Primitives;
使用系统组件模型;
公共类SafeGuiWpf
{
公共静态对象GetTag(控件C)
{
if(C.Dispatcher.CheckAccess())返回C.Tag;
否则返回C.Dispatcher.Invoke(newfunc(GetTag),C);
}
公共静态字符串GetText(文本框TB)
{
if(TB.Dispatcher.CheckAccess())返回TB.Text;
else返回(字符串)TB.Dispatcher.Invoke(newfunc(GetText),TB);
}
公共静态字符串GetText(组合框TB)
{
if(TB.Dispatcher.CheckAccess())返回TB.Text;
else返回(字符串)TB.Dispatcher.Invoke(newfunc(GetText),TB);
}
公共静态字符串GetText(密码箱TB)
{
if(TB.Dispatcher.CheckAccess())返回TB.Password;
else返回(字符串)TB.Dispatcher.Invoke(newfunc(GetText),TB);
}
公共静态void SetText(TextBlock TB,string Str)
{
如果(TB.Dispatcher.CheckAccess())TB.Text=Str;
else TB.Dispatcher.Invoke(新操作(SetText)、TB、Str);
}
公共静态void SetText(文本框TB,字符串Str)
{
如果(TB.Dispatcher.CheckAccess())TB.Text=Str;
else TB.Dispatcher.Invoke(新操作(SetText)、TB、Str);
}
公共静态无效文本(文本框TB,字符串Str)
{
if(TB.Dispatcher.CheckAccess())
{
TB.追加文本(Str);
TB.ScrollToEnd();//是否滚动到末尾?
}
else TB.Dispatcher.Invoke(新操作(AppendText)、TB、Str);
}
公共静态bool?已选中(复选框Ck)
{
if(Ck.Dispatcher.CheckAccess())返回Ck.IsChecked;
else返回(bool?)Ck.Dispatcher.Invoke(newfunc(GetChecked),Ck);
}
公共静态无效设置选中(复选框Ck,bool?V)
{
如果(Ck.Dispatcher.CheckAccess())Ck.IsChecked=V;
else Ck.Dispatcher.Invoke(新操作(SetChecked),Ck,V);
}
公共静态bool GetChecked(菜单项Ck)
{
if(Ck.Dispatcher.CheckAccess())返回Ck
string temp = SafeGuiWpf.GetText(originalTextBox);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.ComponentModel;
public class SafeGuiWpf
{
public static object GetTag(Control C)
{
if (C.Dispatcher.CheckAccess()) return C.Tag;
else return C.Dispatcher.Invoke(new Func<Control, object>(GetTag), C);
}
public static string GetText(TextBox TB)
{
if (TB.Dispatcher.CheckAccess()) return TB.Text;
else return (string)TB.Dispatcher.Invoke(new Func<TextBox,string>(GetText), TB);
}
public static string GetText(ComboBox TB)
{
if (TB.Dispatcher.CheckAccess()) return TB.Text;
else return (string)TB.Dispatcher.Invoke(new Func<ComboBox,string>(GetText), TB);
}
public static string GetText(PasswordBox TB)
{
if (TB.Dispatcher.CheckAccess()) return TB.Password;
else return (string)TB.Dispatcher.Invoke(new Func<PasswordBox, string>(GetText), TB);
}
public static void SetText(TextBlock TB, string Str)
{
if (TB.Dispatcher.CheckAccess()) TB.Text = Str;
else TB.Dispatcher.Invoke(new Action<TextBlock,string>(SetText), TB, Str);
}
public static void SetText(TextBox TB, string Str)
{
if (TB.Dispatcher.CheckAccess()) TB.Text = Str;
else TB.Dispatcher.Invoke(new Action<TextBox, string>(SetText), TB, Str);
}
public static void AppendText(TextBox TB, string Str)
{
if (TB.Dispatcher.CheckAccess())
{
TB.AppendText(Str);
TB.ScrollToEnd(); // scroll to end?
}
else TB.Dispatcher.Invoke(new Action<TextBox, string>(AppendText), TB, Str);
}
public static bool? GetChecked(CheckBox Ck)
{
if (Ck.Dispatcher.CheckAccess()) return Ck.IsChecked;
else return (bool?)Ck.Dispatcher.Invoke(new Func<CheckBox,bool?>(GetChecked), Ck);
}
public static void SetChecked(CheckBox Ck, bool? V)
{
if (Ck.Dispatcher.CheckAccess()) Ck.IsChecked = V;
else Ck.Dispatcher.Invoke(new Action<CheckBox, bool?>(SetChecked), Ck, V);
}
public static bool GetChecked(MenuItem Ck)
{
if (Ck.Dispatcher.CheckAccess()) return Ck.IsChecked;
else return (bool)Ck.Dispatcher.Invoke(new Func<MenuItem, bool>(GetChecked), Ck);
}
public static void SetChecked(MenuItem Ck, bool V)
{
if (Ck.Dispatcher.CheckAccess()) Ck.IsChecked = V;
else Ck.Dispatcher.Invoke(new Action<MenuItem, bool>(SetChecked), Ck, V);
}
public static bool? GetChecked(RadioButton Ck)
{
if (Ck.Dispatcher.CheckAccess()) return Ck.IsChecked;
else return (bool?)Ck.Dispatcher.Invoke(new Func<RadioButton, bool?>(GetChecked), Ck);
}
public static void SetChecked(RadioButton Ck, bool? V)
{
if (Ck.Dispatcher.CheckAccess()) Ck.IsChecked = V;
else Ck.Dispatcher.Invoke(new Action<RadioButton, bool?>(SetChecked), Ck, V);
}
public static void SetVisible(UIElement Emt, Visibility V)
{
if (Emt.Dispatcher.CheckAccess()) Emt.Visibility = V;
else Emt.Dispatcher.Invoke(new Action<UIElement, Visibility>(SetVisible), Emt, V);
}
public static Visibility GetVisible(UIElement Emt)
{
if (Emt.Dispatcher.CheckAccess()) return Emt.Visibility;
else return (Visibility)Emt.Dispatcher.Invoke(new Func<UIElement, Visibility>(GetVisible), Emt);
}
public static bool GetEnabled(UIElement Emt)
{
if (Emt.Dispatcher.CheckAccess()) return Emt.IsEnabled;
else return (bool)Emt.Dispatcher.Invoke(new Func<UIElement, bool>(GetEnabled), Emt);
}
public static void SetEnabled(UIElement Emt, bool V)
{
if (Emt.Dispatcher.CheckAccess()) Emt.IsEnabled = V;
else Emt.Dispatcher.Invoke(new Action<UIElement, bool>(SetEnabled), Emt, V);
}
public static void SetSelectedItem(Selector Ic, object Selected)
{
if (Ic.Dispatcher.CheckAccess()) Ic.SelectedItem = Selected;
else Ic.Dispatcher.Invoke(new Action<Selector, object>(SetSelectedItem), Ic, Selected);
}
public static object GetSelectedItem(Selector Ic)
{
if (Ic.Dispatcher.CheckAccess()) return Ic.SelectedItem;
else return Ic.Dispatcher.Invoke(new Func<Selector, object>(GetSelectedItem), Ic);
}
public static int GetSelectedIndex(Selector Ic)
{
if (Ic.Dispatcher.CheckAccess()) return Ic.SelectedIndex;
else return (int)Ic.Dispatcher.Invoke(new Func<Selector, int>(GetSelectedIndex), Ic);
}
delegate MessageBoxResult MsgBoxDelegate(Window owner, string text, string caption, MessageBoxButton button, MessageBoxImage icon);
public static MessageBoxResult MsgBox(Window owner, string text, string caption, MessageBoxButton button, MessageBoxImage icon)
{
if (owner.Dispatcher.CheckAccess()) return MessageBox.Show(owner, text, caption, button, icon);
else return (MessageBoxResult)owner.Dispatcher.Invoke(new MsgBoxDelegate(MsgBox), owner, text, caption, button, icon);
}
public static double GetRangeValue(RangeBase RngBse)
{
if (RngBse.Dispatcher.CheckAccess()) return RngBse.Value;
else return (double)RngBse.Dispatcher.Invoke(new Func<RangeBase, double>(GetRangeValue), RngBse);
}
public static void SetRangeValue(RangeBase RngBse, double V)
{
if (RngBse.Dispatcher.CheckAccess()) RngBse.Value = V;
else RngBse.Dispatcher.Invoke(new Action<RangeBase, double>(SetRangeValue), RngBse, V);
}
public static T CreateWindow<T>(Window Owner) where T : Window, new()
{
if (Owner.Dispatcher.CheckAccess())
{
var Win = new T(); // Window created on GUI thread
Win.Owner = Owner;
return Win;
}
else return (T)Owner.Dispatcher.Invoke(new Func<Window, T>(CreateWindow<T>), Owner);
}
public static bool? ShowDialog(Window Dialog)
{
if (Dialog.Dispatcher.CheckAccess()) return Dialog.ShowDialog();
else return (bool?)Dialog.Dispatcher.Invoke(new Func<Window, bool?>(ShowDialog), Dialog);
}
public static void SetDialogResult(Window Dialog, bool? Result)
{
if (Dialog.Dispatcher.CheckAccess()) Dialog.DialogResult = Result;
else Dialog.Dispatcher.Invoke(new Action<Window, bool?>(SetDialogResult), Dialog, Result);
}
public static Window GetWindowOwner(Window window)
{
if (window.Dispatcher.CheckAccess()) return window.Owner;
else return (Window)window.Dispatcher.Invoke(new Func<Window, Window>(GetWindowOwner), window);
}
} // END CLASS: SafeGuiWpf
public static string GetTextThreadSafely(this TextBoxBase source)
{
if (source.InvokeRequired)
{
var text = String.Empty;
source.Invoke((Action)(() => { text = source.GetTextThreadSafely(); }));
return text;
}
else
{
return source.Text;
}
}
text = originalTextBox.Dispatcher.Invoke(Function() As String
Return originalTextBox.Text
End Function)