Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
442 views
in Technique[技术] by (71.8m points)

c# - Update UI from different thread

This is my first question here. As English is not my first language, forgive me for any mistakes.

I'm trying to develop an application for Windows Phone 8.1 (XAML and C#) and I'm using .NET Framework 4.5.2. I just started studying multithreading in C# and would appreciate if anyone here could help me. All answers to related questions I've found so far are too complex.

All I need is to create a new task from a button click that displays a message in a textblock control.

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

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

I'm getting the following exception: The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)).

How can I correct this?

Thanks in advance!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

This is the 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;
        }
    }
}

Basically what it you are doing is passing in a Progress that you can use with your task.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.8k users

...