2015-07-11 71 views
0

我正在学习使用线程并进行一些多线程演示。

我有一个名为lblText的标签和一个名为pgbRun的选取框进度条。我制作了2个线程,一个让标签的文本在每个Thread.Sleep()调用后更改,其他让标签的文本更改时进度条显示动画。

我遇到的问题是文本更改线程似乎工作正常,但进度条线程有问题。 pgbRun刚刚开始动画后文本更改完成。

请帮我看看我的代码有什么问题,并告诉我一些解决问题的方法。非常感谢!跑马灯进度条有问题

private delegate void formDelegate(); 

private void btnRun_Click(object sender, EventArgs e) 
{ 
    Thread thread = new Thread(new ThreadStart(new formDelegate(textChange))); 
    thread.IsBackground = true; 
    thread.Start(); 
} 

public void textChange() 
{ 
    if (lblText.InvokeRequired) 
    { 
     lblText.BeginInvoke(new formDelegate(textChange)); 
    } 
    else 
    { 
     Thread thread = new Thread(new ThreadStart(new formDelegate(progess))); 
     thread.IsBackground = true; 
     thread.Start(); 

     //I try make single thread that config progress bar here but i have same trouble. 

     for (int i = 0; i < 10; i++) 
     { 
      lblText.Text = "Count: " + i; 
      lblText.Update(); 
      lblText.Refresh(); 
      Thread.Sleep(300); 
     } 
    } 
} 

public void progess() 
{ 
    if (pgbRun.InvokeRequired) 
    { 
     pgbRun.BeginInvoke(new formDelegate(progess)); 
    } 
    else 
    { 
     pgbRun.Style = ProgressBarStyle.Marquee; 
     pgbRun.MarqueeAnimationSpeed = 20; 
     pgbRun.Update(); 
     pgbRun.Refresh(); 
    } 
} 
+1

你的线程没有做任何有用的事情,他们立即调用到UI线程。 textChange()代码不能完成更多的事情,但会导致UI挂起3秒钟。您可以看到标签更改,因为您调用Update()。 projss()中的BeginInvoke()调用在UI线程忙于睡眠3秒内停滞不前,因此您没有看到进度条发生任何事情。你需要抛弃这些代码。 –

+0

@HansPassant,我该如何解决它? – tungns304

回答

0

当我读到this very useful article后,我看到#Hans是如此的真实。我的第一个代码是垃圾,所以我编辑我的代码如下。进度条的基本属性在设计器中设置,在代码中我只是更改可见选项。

delegate void textChangeDelegate(int x); 

private void btnRun_Click(object sender, EventArgs e) 
{ 
    Thread thread = new Thread(new ThreadStart(new MethodInvoker(threadJob))); 
    thread.IsBackground = true; 
    thread.Start(); 
} 

public void threadJob() 
{ 
    Invoke(new MethodInvoker(show)); 
    for (int i = 0; i < 10; i++) 
    { 
     Invoke(new textChangeDelegate(textChange),new object[]{i}); 
     Thread.Sleep(500); 
    } 
    Invoke(new MethodInvoker(hide)); 
} 

public void textChange(int x) 
{ 
    if (InvokeRequired) 
    { 
     BeginInvoke(new textChangeDelegate(textChange),new object[] {x}); 
     return; 
    } 
    x += 1; 
    lblText.Text = "Count: " + x; 
} 

public void show() 
{ 
    pgbRun.Visible = true; 
    lblText.Visible = true; 
} 

public void hide() 
{ 
    pgbRun.Visible = false; 
    lblText.Text = ""; 
    lblText.Visible = false; 
} 
0

您应该为此使用Microsoft的Reactive Framework。这会让它变得更容易。

下面的代码:

private void btnRun_Click(object sender, EventArgs e) 
{ 
    Observable 
     .Interval(TimeSpan.FromMilliseconds(300.0)) 
     .Take(10) 
     .Select(n => String.Format("Count: {0}", n)) 
     .ObserveOn(this) 
     .Subscribe(t => lbl.Text = t); 
} 

就是这样。

Just NuGet“Rx-WinForms”并将其添加到您的项目中。

目前还不清楚你试图用进度条做什么。你能否提供更详细的信息?

+0

感谢您的回答。我试图用两个线程创建一个多线程演示。一个改变标签的文本,其他“打开”进度条,而这些文本正在充电。我非常感谢你用这个漂亮的框架,但我需要解决线程和多线程问题。所以你的解决方案在未来应该对我有用。 – tungns304

+0

@ tungns304 - 这是多线程。它只是使用一个为您管理线程的框架。 'ObserveOn(this)'之前的所有内容都发生在后台线程上,然后再回到UI线程上。 – Enigmativity

+0

听起来不错。让我看看那里的文件。 – tungns304