2009-04-02 11 views
8

私のWPFフォームには、テキストボックスがあります。
タイマーが経過すると、テキストボックスの内容を取得する必要があります。
経過したタイマーは、UIと異なるスレッドで動作しています。 GUIスレッドクロススレッドから値を読み取るための最も簡単な、最も読みやすい方法です(私はいくつか発見し、彼らは何かがどうあるべきかについて、あまりにも冗長に見える何WPFの別のスレッドからtextbox.Text値を読み取る方法は?

  • 質問はちょっと2倍です本当に基本的な)?

  • ノンブロッキングでテキストを読み取ることはできませんか?この場合、スレッドの安全性は気にしません。

--EDIT--
私は、ディスパッチャを使用しますが、Johnが持っていたものを、より詳細なコールを持っていた:

originalTextBox.Dispatcher.Invoke(
    DispatcherPriority.Normal, 
    (ThreadStart) delegate{text=originalTextBox.Text;} 
); 

はしかしさえterser気にしないだろう。テキストプロパティへのアクセスは完全に基本的なものでなければなりません。

答えて

1

GUIオブジェクトの値を、それを作成したスレッドとは異なるスレッドから読み取るための「クイックハック」はありません。 WPFはあなたがそれをすべて行うことを許可しません。 Windowsフォームは間違いなく不平を言いますが、WPFはもっと厳しいです。

ディスパッチャについて知る必要があります。冗長に見えるかもしれませんが、実際に理解するのは難しいことではありません。ディスパッチャにデリゲートを渡して、GUIスレッドで呼び出すメソッドをポイントします。

はここで素敵な簡単な例です:

http://www.switchonthecode.com/tutorials/working-with-the-wpf-dispatcher

+1

スレッドセーフな値を呼び出す方法はありませんか?私はそれを取得する必要があります、それを設定しないでください。 –

+0

私は素早くハックを探しているわけではありません。私は何か読めるものを探しています。あなたがするならば、短い手。 –

+0

バブルを破棄して申し訳ありませんが、ディスパッチャは簡略化されています。 :)あなたはあなた自身のディスパッチャ/マーシャラーを書いてみたいですか? – x0n

5

Oisinは右である、あなたはDispatcherを見てする必要があります。このような何かが動作し、あまりにも冗長ではないはずです。

System.Windows.Application.Current.Dispatcher.Invoke(
DispatcherPriority.Normal, 
(ThreadStart)delegate { text = MyTextBox.Text; }); 
+0

まあそれは私がoriginalTextBox.Dispatcher.Invokeを持っていたもの、その後良いでしょう( DispatcherPriority.Normal、 新しいアクション( デリゲート(){ テキスト= originalTextBox.Text; })); –

5

次のいずれかを実行できます

  • は、バックグラウンドスレッドからUIスレッド上で実行するためにメッセージをスケジュールするDispatcherを使用してください。 DispatcherPrioritySendの場合、最も速い応答が得られます。
  • DispatcherTimerを使用して、UIスレッドで定期的にメッセージを実行します。
  • OneWayToSourceバインディングを使用して、Textプロパティをバックグラウンドコンポーネントのプロパティに接続します。そうすれば、プロパティ値を取得するための作業を行う必要はありません。これは既にコンポーネントに供給されています。
0

私のsolutiosn ... 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

をruningている間に第二テキストボックスには、タイプのテストのためにありますWilcoxのSmartDispatcherクラスです。

どこかのコンストラクタまたはロードイベントでSmartDispatcher.Initialize()(UIディスパッチャを設定する)

が次にどこにプロパティを設定したり、メソッドを呼び出す必要があります:

Action a = delegate { <statements> }; 
SmartDispatcher.BeginInvoke(a); 

これは、UIスレッド上にあるかどうかを知る必要はなく、両方から行う必要があるかもしれません。 SmartDispatcherは、必要に応じてスレッドスイッチを処理します。

上記は非同期ですが、同期が必要な場合は、BeginInvokeではなくInvokeを呼び出す別のメソッドを追加するだけです。

1

ちょうどここに遭遇してしまいます。しばらくして、いくつかの共通のコントロールプロパティに素早くアクセスするためにプロジェクトに追加できる静的クラスを構築し始めました。時間が経つと膨らみますが、多くのディスパッチャコードを隠している間はかなり簡単になります。原油だが効果的。あなたにいくつかのアイデアがあります。 私は基本的にこのようなこと行うことができます:ここでは

string temp = SafeGuiWpf.GetText(originalTextBox); 

は、あなたはそれが役に立つ見つけた場合SafeGuiWpfは最後の、ように見えたものです。

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 

振り返ってみると(それがNET 3、最大でうまくいくと思うが、それはしばらくしている)、彼らはさらに滑らかな私は、クラスの拡張としてこれらをした場合は作っている場合があります。

1

私はこれを回避するには、以下の拡張メソッドを使用します。

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; 
     } 
    } 

そしてもちろん、この方法は、別の静的クラスに追加する必要があります。

+1

恐ろしい!本当に素晴らしい解決策!私は私のWinFormプロジェクト内でそれを適用しました(私はそれを一般化しました)!それは素晴らしい作品です! –

関連する問題