2016-06-04 11 views
0

Dies ist meine erste Frage hier. Da Englisch nicht meine Muttersprache ist, vergib mir Fehler.Update UI aus anderen Thread

Ich versuche, eine Anwendung für Windows Phone 8.1 (XAML und C#) zu entwickeln, und ich verwende .NET Framework 4.5.2. Ich begann gerade Multithreading in C# zu lernen und würde mich freuen, wenn mir hier jemand helfen könnte. Alle Antworten auf verwandte Fragen, die ich bisher gefunden habe, sind zu komplex.

Alles, was ich brauche, ist eine neue Aufgabe von einem Knopf Klick erstellen, die eine Nachricht in einem Textblock-Steuerelement anzeigt.

private void myButton_Click(object sender, RoutedEventArgs e) 
{ 
    Task t = new Task(MyMethod); 
    t.Start(); 
} 

private void MyMethod() 
{ 
    myTextBlock.Text = "Worked!"; 
} 

Ich bekomme die folgende Ausnahme: Die Anwendung rief eine Schnittstelle, die für einen anderen Thread marshalled wurde. (Ausnahme von HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)).

Wie kann ich das korrigieren?

Vielen Dank im Voraus!

+2

Mögliche Duplikat verwenden können [ Wie aktualisiert man die GUI von einem anderen Thread in C#?] (Http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c) – MickyD

+0

Suche nach App. Current.Dispatcher.Invoize auf diese Weise können Sie eine Aktion im Hauptthread aufrufen, ich denke, das ist was Sie suchen. gl! – natschz

Antwort

0

Wenn Sie das Programmiermodell async/await verwenden, können Sie dies ganz einfach tun.

Statt dessen, was Sie haben, versuchen Sie so etwas wie dieses:

private async void myButton_Click(object sender, RoutedEventArgs e) 
{ 
    Task t = MyMethod(); 
    await t; 
} 

private async Task MyMethod() 
{ 
    myTextBlock.Text = "Worked!"; 
} 
+0

Danke! Das war genau das, was ich brauchte. Nur noch zwei Fragen: 1 - Sollte ich nicht 'erwarten' Operator im Code der privaten async Task MyMethod()? 2 - Können Sie weitere Informationen zu Multithreading und async/awa in C# vorschlagen? Danke nochmal! – Alexandre

+1

https://msdn.microsoft.com/en-us/magazine/jj991977.aspx http://blog.stephencleary.com/2012/02/async-and-await.html Und der Rest von Stephen Cleary Blog. Ich habe meine Informationen aus einer Kombination von ihm und CLR über C# von Jeremy Richter gelernt. Sie müssen in MyMethod nichts abwarten, Sie können die Warnung in diesem Fall ignorieren. – bodangly

+0

@Alexandre Übrigens scheint mir dein Englisch ziemlich genau zu sein, hätte nie gedacht, dass es nicht deine Muttersprache ist. – bodangly

0

Designer Code:

namespace Tasks 
{ 
    partial class Form1 
    { 
     /// <summary> 
     /// Required designer variable. 
     /// </summary> 
     private System.ComponentModel.IContainer components = null; 

     /// <summary> 
     /// Clean up any resources being used. 
     /// </summary> 
     /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
     protected override void Dispose(bool disposing) 
     { 
      if (disposing && (components != null)) 
      { 
       components.Dispose(); 
      } 
      base.Dispose(disposing); 
     } 

     #region Windows Form Designer generated code 

     /// <summary> 
     /// Required method for Designer support - do not modify 
     /// the contents of this method with the code editor. 
     /// </summary> 
     private void InitializeComponent() 
     { 
      this.button1 = new System.Windows.Forms.Button(); 
      this.button2 = new System.Windows.Forms.Button(); 
      this.textBox1 = new System.Windows.Forms.TextBox(); 
      this.SuspendLayout(); 
      // 
      // button1 
      // 
      this.button1.Location = new System.Drawing.Point(41, 43); 
      this.button1.Name = "button1"; 
      this.button1.Size = new System.Drawing.Size(75, 23); 
      this.button1.TabIndex = 0; 
      this.button1.Text = "button1"; 
      this.button1.UseVisualStyleBackColor = true; 
      this.button1.Click += new System.EventHandler(this.button1_Click); 
      // 
      // button2 
      // 
      this.button2.Location = new System.Drawing.Point(131, 43); 
      this.button2.Name = "button2"; 
      this.button2.Size = new System.Drawing.Size(75, 23); 
      this.button2.TabIndex = 1; 
      this.button2.Text = "button2"; 
      this.button2.UseVisualStyleBackColor = true; 
      this.button2.Click += new System.EventHandler(this.button2_Click); 
      // 
      // textBox1 
      // 
      this.textBox1.Location = new System.Drawing.Point(41, 84); 
      this.textBox1.Name = "textBox1"; 
      this.textBox1.Size = new System.Drawing.Size(165, 20); 
      this.textBox1.TabIndex = 2; 
      // 
      // Form1 
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
      this.ClientSize = new System.Drawing.Size(240, 151); 
      this.Controls.Add(this.textBox1); 
      this.Controls.Add(this.button2); 
      this.Controls.Add(this.button1); 
      this.Name = "Form1"; 
      this.Text = "Form1"; 
      this.ResumeLayout(false); 
      this.PerformLayout(); 

     } 

     #endregion 

     private System.Windows.Forms.Button button1; 
     private System.Windows.Forms.Button button2; 
     private System.Windows.Forms.TextBox textBox1; 
    } 
} 

Dies ist die Form Code:

using System; 
using System.Diagnostics; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Windows.Forms; 

namespace Tasks 
{ 
    public partial class Form1 : Form 
    { 
     //Just incase you need to stop the current task 
     CancellationTokenSource cts; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button2_Click(object sender, EventArgs e) 
     { 
      //showing that the form is still working 
      MessageBox.Show(this,"This button still works :)"); 
     } 

     private async void button1_Click(object sender, EventArgs e) 
     { 
      cts = new CancellationTokenSource(); 

      await CreateTask(); 
     } 

     private async Task CreateTask() 
     { 
      //Create a progress object that can be used within the task 
      Progress<string> mProgress; //you can set this to Int for ProgressBar 
      //Set the Action to a function that will catch the progress sent within the task 
      Action<string> progressTarget = ReportProgress; 
      //Your new Progress with the included action function 
      mProgress = new Progress<string>(progressTarget); 

      //start your task 
      string result = await MyProcess(mProgress); 

      MessageBox.Show(this, result); 
     } 

     //notice the myProgress this can be used within your task to report back to UI thread. 
     private Task<string> MyProcess(IProgress<string> myProgress) 
     { 
      return Task.Run(() => 
      { 
       //here you will sen out to your UI thread whatever text you want. 
       //typically used for progress bar. 
       myProgress.Report("It Works.."); 
       //your tasks return 
       return "Yes it really does work..."; 

      }, cts.Token); 
     } 

     private void ReportProgress(string message) 
     { 
      //typically to update a progress bar or whatever 
      //this is where you Update your UI thread with text from within the Task. 
      textBox1.Text = message; 
     } 
    } 
} 

Im Grunde, was es Sie tun, ist in einem Fortschritt vorbei, die Sie mit Ihrer Aufgabe verwenden können.

+0

Sie sollten wahrscheinlich erklären, was hier vor sich geht, damit dies wirklich hilfreich ist. – bodangly

+0

Hinzugefügt Kommentare innerhalb des Codes. Um zu helfen, die Lösung zu verstehen. – EJD

0

Wenn Sie in einem Windows Phone (WinRT, nicht Silverlight) sind Projekt Sie auch

await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(() => 
     { 
      // your code 
     }));