各位大虾:
    Form1里有两个Button一个label1,点button1后启动另一个线程来生成一个Class2的对像,Class2中有个timer每隔500ms使i加一,并通过Form1的Label显示出来;点button2后不启动另一个线程,直接生成一个Class2的对像。为什么点button1不管用也不提示错误,Form1中的Label未变化。而点button2后正常??????????
   代码如下//---------------------Form1-------------------------using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;namespace WindowsApplication2
{
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Label label1;
public static System.Windows.Forms.Label label_S;
private System.Windows.Forms.Button button2;
private System.ComponentModel.IContainer components;
public Form1()
{
InitializeComponent();
Form1.label_S=this.label1;
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null) 
{
components.Dispose();
}
}
base.Dispose( disposing );
} #region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.button2 = new System.Windows.Forms.Button();
this.SuspendLayout();
// 
// button1
// 
this.button1.Location = new System.Drawing.Point(80, 16);
this.button1.Name = "button1";
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.Click += new System.EventHandler(this.button1_Click);
// 
// label1
// 
this.label1.Location = new System.Drawing.Point(72, 104);
this.label1.Name = "label1";
this.label1.TabIndex = 1;
this.label1.Text = "label1";
// 
// button2
// 
this.button2.Location = new System.Drawing.Point(208, 32);
this.button2.Name = "button2";
this.button2.TabIndex = 2;
this.button2.Text = "button2";
this.button2.Click += new System.EventHandler(this.button2_Click);
// 
// Form1
// 
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.button2);
this.Controls.Add(this.label1);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false); }
#endregion
[STAThread]
static void Main() 
{
Application.Run(new Form1());
}
public static void TheadS()
{
Class1 c1=new Class1();
c1.Start();
}
private void button1_Click(object sender, System.EventArgs e)
{
Thread td=new Thread(new ThreadStart(TheadS));//创建另一个线程启动Label并无变化。
td.Start();
} private void button2_Click(object sender, System.EventArgs e)
{
TheadS();// 直接启动显示正常。
}
}
}//--------------------Class1---------------------
using System;
using System.Windows.Forms;
namespace WindowsApplication2
{
public class Class1
{
private System.Windows.Forms.Timer timer1=new Timer();
private int i=0;
public Class1()
{
this.timer1.Tick+=new EventHandler(timer1_Tick);
this.timer1.Interval=500; }
public void Start()
{
this.timer1.Start();
} private void timer1_Tick(object sender, EventArgs e)
{
Form1.label_S.Text=(i++).ToString();
}
}
}

解决方案 »

  1.   

    子线程一般是难以改变UI界面的,可用控件的Invoke方法,你可以参考一下下面这个例子
    // 为清楚起见,省略了一些成员
       public void btnAdd_OnClick(object sender, EventArgs e)
       {
           // 在创建 _txtSum 的线程上执行 UpdateSumDisplay
          _txtSum.Invoke(new EventHandler(UpdateSumDisplay));
       }
       public void UpdateSumDisplay(object sender, EventArgs e)
       {
          _txtSum.Text = _sum.ToString();
       }
      

  2.   

    levinknigh:能不能说详细点啊?谢谢
      

  3.   

    netsd:是难以改变UI界面的,在需要用Invoke方法而你并没有时,编译器会提示错误的。而现在这个程序并未提示错误。
      

  4.   

    是不是因为生成的Class1对象被清理掉了。
      

  5.   

    netsd(极品非车)说的对
    具体如下
    定义一个委托
    delegate void UpdateSumDisplay();
    然后修改button1_Click的代码为如下
    label1.BeginInvoke(new UpdateSumDisplay(TheadS));
      

  6.   

    ljasmine:你的方法可以正常运行。但我仍想不明白,我在Class1的timer_tick函数里加了一个播放一个小声音的语句,不涉及访问Form1的控件的属性,用以前我的方法启动线程,仍然不成功,没听到声音,也就是说Class1的timer_tick函数里的语句跟本就没有执行,这是为什么????
      

  7.   

    不要在创建控件以外的线程操作控件,.Net 2.0已经把这个作为异常了。可以使用Control的Invoke方法,将操作放到UI线程上。private void Form1_Load(object sender, System.EventArgs e)
    {
        System.Threading.Thread tNew = new System.Threading.Thread    (new     System.Threading.ThreadStart(this.Test));
        tNew.Start();
    }delegate void SetVisibleDelegate();private void SetVisible()
    {
       this.button1.Visible = true;
    }private void Test()
    {
       this.Invoke(new SetVisibleDelegate(SetVisible));
    }
      

  8.   

    现在我已经不用Label显示数据来证明Class1的timer在工作了,我用播放声音的方法,如果听到声音就说明timer在工作,但跟本听不到声音啊
      

  9.   

    我试了播放声音没问题
    [DllImport("kernel32.dll")] 
    public static extern bool Beep(int frequency, int duration);
      

  10.   

    ljasmine:播放声音点button1不管用,点button2没问题。我是说用楼顶的方法启动线程,而不是用BeginInvoke方法。
      

  11.   

    刚才试了一下,确实用你的方法不能播放声音,程序根本就不激发timer1_Tick事件,查了帮助文件如下说:
    System.Windows.Forms.Timer
    实现在用户定义的时间间隔引发事件的计时器。此计时器最宜用于 Windows 窗体应用程序中,并且必须在窗口中使用。
      

  12.   

    必须在窗口中使用我觉得不是主要原因,如果不用另一个线程启动的话那个Class1类运行的很好。而且在我另处的程序里,我没有用timer控件也没有用其它任何窗体控件,问题仍然存在,不知何故???
      

  13.   

    MSDN上说的Windows 窗体应用程序应该是和控制台应用程序等对立的,上面那个程序本是就是Windows 窗体应用程序了。所以我觉得问题应该不会出在timer身上。
      

  14.   

    嗯,这个就不知道了。不过我另外一个程序里有同样的问题,我没用timer,只用了事件,是不是事件不能用。
      

  15.   

    Form1.label_S.Text=(i++).ToString();
    Form1.Update();界面没更新,更新一下,值就变了。
      

  16.   

    事实上timer1的tick事件并没有被执行,更不更新的无所谓,而且后面已经不用Label显示数据来证明Class1的timer在工作了,改用播放声音的方法,如果听到声音就说明timer在工作,但仍然听不到声音