簡體   English   中英

文字未更新

[英]Text not updating

我有兩個類;一個叫Form1.cs,另一個叫NoteThreader.cs,這是兩個類的內容:

Form1.cs中:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace HitMachine
{
 public partial class Form1 : Form
 {
    public Form1()
    {
        InitializeComponent();
    }

    public void updateText(string theText)
    {
        label1.Text = theText;
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        XML.LoadMP3.loadFile(XML.XmlParser.ParseDocument("music"));
        Threading.NoteThreader.createTimer();
    }
  }
}

NoteThreader.cs:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;

    namespace HitMachine.Threading
    {
        public class NoteThreader
        {
            public static Thread createTimer()
            {
                Thread t = new Thread(threadDeligation);
                t.Start();

                return t;
            }

            public static int time = 0;

            static void threadDeligation()
            {
                for (; ; )
                {
                    Form1 a = new Form1();
                    a.updateText(time);
                    time++;
                }
            }
        }
    }

代碼運行無任何異常或錯誤; 但是它不會更新文本。 我猜是因為調用該方法的線程與更新文本的線程不同?

我嘗試調用它,但無法執行。 我在threadDeligation中運行了一個MessageBox,並且工作正常。

在您的threadDeligation方法中,每次循環執行時都在創建一個Form1的新實例。 這不會更改您正在查看的Form1實例中的文本。

您將需要將Form1的正確實例傳遞給createTimer方法(然后將其傳遞給threadDeligation方法)。

您可以這樣處理:

private void Form1_Load(object sender, EventArgs e)
{
    XML.LoadMP3.loadFile(XML.XmlParser.ParseDocument("music"));
    Threading.NoteThreader.createTimer(this);
}

接着:

public static Thread createTimer(Form1 theForm)
{
    Thread t = new Thread(() => threadDeligation(theForm));
    t.Start();
   return t;
}

public static int time = 0;

static void threadDeligation(Form1 theForm)
{
    for (; ; )
    {
         theForm.updateText(time);
         time++;
    }
}

這應該給你如何在你的代碼通過周圍物體的總體思路,但由於從非UI線程更新UI元素,不支持將無法正常工作。 您將需要使用BackgroundWorker類。

for (; ; )
{
    Form1 a = new Form1();
    a.updateText(time);
    time++;
}
  1. 每次迭代都會創建一個新的Form1對象。
  2. a.Show();在哪里a.Show();

如果要顯示計時器的值,則應保留對適當的Form1對象的引用。

因此,這里有很多問題。 首先是其他答案提到的顯而易見的內容。 您正在創建Form1新實例並調用其方法,然后修改其標簽。 您沒有修改要顯示給用戶的表單; 它沒有改變。

如果要保留正在使用的表單的實例,則會遇到從另一個線程修改表單的問題。 那是不允許的。 在Winform編程中,只允許從創建它們的線程訪問Control對象。 否則會出錯。

為了解決這個問題,您可以調用主UI線程進行更新。 但是,現在您處於發送命令以盡可能快地發送標簽更新標簽的位置。 那...非常非常非常快。 如此之快以至於屏幕根本無法更新。 由於發送的命令數量巨大,您將開始滯后甚至凍結。

似乎您想創建某種臨時時鍾,在其中您每隔X個時間間隔增加一個數字。 假設每秒一次(但您可以輕松地將其更改為10毫秒或任何其他時間)。 為了在X時間間隔內執行某項操作,我們需要使用Timer

void Form1_Load(object sender, EventArgs e)
{
    var timer = new System.Windows.Forms.Timer();
    timer.Interval = 1000;
    timer.Tick += timer_Tick;
    timer.Start();
}

private int time = 0;
void timer_Tick(object sender, EventArgs e)
{
    label1.Text = time.ToString();
    time++;
}

如果按照命名約定,而不是每隔X間隔執行一次操作,而不是每隔X間隔執行一次操作,而是根據生產進度進行一些富有成效的工作並更新用戶界面,那么那就是另一個問題了。 一個不錯的選擇是使用Progress類使用一些非UI任務的Progress來更新UI。 它可能看起來像這樣:

void Form1_Load(object sender, EventArgs e)
{
    Progress<string> progress = new Progress<string>(updateText);
    Thread thread = new Thread(() => NoteThreader.DoWork(progress));
    thread.Start();
}

public class NoteThreader
{
    public static void DoWork(IProgress<string> progress)
    {
        for (int i = 0; i < 10; i++)
        {
            Thread.Sleep(1000);//placeholder for real work
            progress.Report(i.ToString());
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM