2017-02-14 7 views
-1

私はUIオブジェクトとの間でデータを取得および設定することに苦労しています。 Invokingを使って、これをBackgroundWorker-Threadから行うことが可能です。悲しいことに私はメソッドを呼び出すことでしか見つけられなかったし、ラベルや他のものを束ねるのにうまくいきましたが、DataGridViews、ComboおよびTextBoxesには失敗しました。私は次のコードでこれを使用してみましたが、それはうまくいきませんでした言ったようにBackgroundWorker-ThreadからUIオブジェクトにデータを取得/設定する

this.uiObject.Invoke((MethodInvoker)delegate 
{ 
    this.uiObject.Text = "Hello World";//Setting Label Text from BackgroundWorker 
}); 

:これは私が話して呼び出し「コード」です。

private void loadPlaylists() 
{ 
    this.playlistGrid.Rows.Clear();//Invoke on a DataGridView 

    string filePath = this.genrePath + this.sortBox.SelectedItem.ToString() + ".txt"; 
    if (File.Exists(filePath) && File.ReadAllText(filePath) != "") 
    { 
     using (StreamReader sr = new StreamReader(filePath)) 
     { 
      bool first = false; 
      string line = ""; 
      while ((line = sr.ReadLine()) != null) 
      { 
       if (first && line != "") 
       { 
        string[] split = line.Split(new string[] { " // " }, StringSplitOptions.None); 

        FullPlaylist playList = spotify.GetPlaylist(split[1], split[0]); 

        this.playlistGrid.Rows.Add(playList.Name, playList.Owner.Id);//Invoke on a DataGridView 
       } 
       if (line != "") 
        first = true; 
      } 
     } 
    } 
} 

private void loadItems(bool newItem = false, bool deletedItem = false, string name = "") 
{ 
    this.sortBox.Items.Clear();//Invoke on a ComboBox 

    DirectoryInfo dir = new DirectoryInfo(this.genrePath); 
    foreach (var file in dir.GetFiles("*.txt")) 
    { 
     string[] split = file.Name.Split(new string[] { ".txt" }, StringSplitOptions.None); 
     this.sortBox.Items.Add(split[0]);//Invoke on a ComboBox 
    } 

    if (newItem) 
    { 
     this.sortBox.SelectedItem = name;//Invoke on a ComboBox 
     this.mode = 5; 
    } 

    if (deletedItem) 
    { 
     if (this.sortBox.Items.Count > 0)//Invoke on a ComboBox 
     { 
      this.sortBox.SelectedIndex = 0;//Invoke on a ComboBox 
      this.mode = 5; 
     } 
     else 
      this.playlistGrid.Rows.Clear();//Invoke on a DataGirdView 
    } 
} 

private void addPlaylists() 
{ 
    string[] split; 
    string filePath = ""; 
    if (this.sortBox.SelectedIndex != -1)//Invoke on a ComboBox 
    { 
     filePath = this.genrePath + this.sortBox.SelectedItem.ToString() + ".txt";//Invoke on a ComboBox 
    } 
    else 
    { 
     MetroFramework.MetroMessageBox.Show(this, "Select a valid Category first!", 
      "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
     return; 
    } 
    if (this.playlistLink.Text != "" && this.playlistLink.Text.Contains("/"))//Invoke on a TextBox 
    { 
     if (this.playlistLink.Text.Contains("|"))//Invoke on a TextBox 
     { 
      split = this.playlistLink.Text.Split('|');//Invoke on a TextBox 
     } 
     else 
     { 
      split = new string[1]; 
      split[0] = this.playlistLink.Text;//Invoke on a TextBox 
     } 

     for (int j = 0; j < split.Length; j++) 
     { 
      string[] split2 = split[j].Split('/'); 
      string id = split2[split2.Length - 1], owner = split2[split2.Length - 3]; 
      FullPlaylist playlist = this.spotify.GetPlaylist(owner, id); 
      string write = id + " // " + owner + " // " + playlist.Name; 
      this.changeOrAddLine(filePath, write, write); 
     } 

     this.playlistLink.Text = "";//Invoke on a TextBox 

     this.loadPlaylists();//Call to a Methode, where Invoke is needed 
    } 
    else if (!this.playlistLink.Text.Contains("/"))//Invoke on a TextBox 
    { 
     //Error 
     this.playlistLink.Text = "";//Invoke on a TextBox 
    } 
    else 
    { 
     //Error 
    } 
} 

これは、私がBackgrounddWorkerから呼び出す3つのメソッドです。コードは正常で、BackgroundWorkerの外で動作します。 UI-Projectを使って何かをしているので、Invoking(必要であれば)を使用する必要があるすべての行をマークしました。私はあなたの誰かが私にこれを行う方法を教えてくれることを願っています。私はコードを覚えて修正を加えることを期待していませんが、これを行う方法の全体的な例はうまくいくはずです。前もって感謝します!

答えて

0

どこでもUIコントロールに影響しますが、そのロジックを呼び出し呼び出しでラップします。例えば、ではなくて:

this.playlistGrid.Rows.Clear(); // No 

これを行います。

uiObject.Invoke(() => this.playlistGrid.Rows.Clear()); // Yes 

これは、効果的に時間が右UIのメッセージループのときにその操作を実行するためにUIスレッドにメッセージを送信します。このような呼び出しでUIコントロールとのすべての対話をラップすると、エラーは終了するはずですが、Invokeの結果を待つ間はバックグラウンドスレッドをブロックしていることに注意してください。 UIスレッドが、バックグラウンドスレッドの待機を待っていないこと、またはデッドロックが発生していることを確認してください。 BeginInvokeを使用してこれを回避することができますが、操作がすぐには発生しない可能性があることに注意する必要があります。たとえば、あなたがコントロールから何かを読みたい場合は、ないこの操作を行います。あなたは、一般的に、あなたの非同期アクションを起動し、それを渡す前に、あなたのUI層でのコントロールからすべてのデータを収集したほうが良いです

string localValue = null; 
uiObject.BeginInvoke(() => { localValue = this.sortBox.SelectedItem.ToString(); }); 
// should NOT assume you can use localValue here 

をバックグラウンドプロセス例:

private void loadPlaylists(string selectedItem) 
+0

"this.playlistGrid.Invoke(>)this.playlistGrid.Rows.Clear());"エラーが発生します。 –

+0

あなたはどんなエラーがありますか? – N8allan

+0

** "ラムダ式"はデリゲート型ではないので "Delegate"型に変換できません**(ドイツ語から英語に大体翻訳) –

関連する問題