我的关于线程的一些不理解的问题,请高手请教!!
我写了一个Windows应用程序,在程序运行起来,启动一个线程,进行数据库操作,开始的时候我的线程函数是普通的类的程序函(就是主窗体这个类的程序函数),但是在调试时,发现程序进入线程中,就跑飞了,于是我换成静态函数,运行就没有问题。后来我想在线程函数运行过程中操作窗体中的控件,我打算使用委托来实现线程中操作控件,但是静态函数中好像又不能使用委托的对象,编译报错:非静态变量需要静态引用。现在不知道该怎么做了!!
我的疑问是:
1、线程函数使用静态与非静态的函数,什么情况下使用静态,什么时候使用非静态,有什么区别;
2、线程函数与主窗口在同一个类中,使用静态,还是非静态的,使用非静态的为社么会出现我上述的程序跑飞的问题;
请高手指教一下!!!! --------------------编程问答--------------------
把我的测试代码发一下:
Form1.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace ThreadDemo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public static void mythreadproc() //线程函数
{
//int i = 0;
for (int i = 0; i < 100; i++)
{
Console.WriteLine(i.ToString());
Thread.Sleep(1000);
}
}
private void Form1_Load(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(mythreadproc));
t.Start();
}
}
}
///////////////
如果把函数mythreadproc改为非静态的,那么程序就会跑飞掉,请问这是怎么回事?? --------------------编程问答-------------------- 这个跟程序的Main函数一定要是静态函数是一个道理,如果入口函数是非静态函数,则在类实例化之前该函数不会被分配内存空间,线程也不会找到启动的入口点。静态函数在程序编译好后类加载时就会被分配内存空间,这样线程才能启动。 --------------------编程问答-------------------- 你所谓的跑飞了是什么意思。
线程 t 不能控制还是》。。。 --------------------编程问答-------------------- 但是我在网上看到很多线程函数不是静态的情况, --------------------编程问答--------------------
就是在线程函数入口设置一个断点,然后F10之后程序就不知道去哪里了??
另外,我看这个例子也是使用非静态函数作为线程函数??
http://www.4vsky.com/blogview.asp?logID=20 --------------------编程问答-------------------- 啥叫"跑飞"? --------------------编程问答-------------------- 并不是程序跑飞掉,而是进程停止了。同意2楼的观点。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace ThreadDemo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void mythreadproc() //线程函数
{
//int i = 0;
for (int i = 0; i < 100; i++)
{
Console.WriteLine(i.ToString());
Thread.Sleep(1000);
}
}
static void main()
{ Form1 F1 = new Form1();
F1.yourThread();
}
public void yourThread ()
{ Thread t = new Thread(new ThreadStart(mythreadproc));
t.Start();
}
}
}
--------------------编程问答-------------------- 并不是程序跑飞掉,而是“线程”停止了。同意2楼的观点。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace ThreadDemo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void mythreadproc() //线程函数
{
//int i = 0;
for (int i = 0; i < 100; i++)
{
Console.WriteLine(i.ToString());
Thread.Sleep(1000);
}
}
static void main()
{ Form1 F1 = new Form1();
F1.yourThread();
}
public void yourThread ()
{ Thread t = new Thread(new ThreadStart(mythreadproc));
t.Start();
}
}
}
照你那样,当start函数返回的时候,线程就会终止。或者没有调用Start,你调用其它函数,做其它动作也会终止。 --------------------编程问答-------------------- 我的疑问是:
1、线程函数使用静态与非静态的函数,什么情况下使用静态,什么时候使用非静态,有什么区别;
2、线程函数与主窗口在同一个类中,使用静态,还是非静态的,使用非静态的为社么会出现我上述的程序跑飞的问题;
答:
1:静态与非静态函数对于线程来说没有本质上的区别。使用静态与非静态完全取决于你的线程的需要。
静态函数适合于线程数目固定的情况。比如你需要一个精度不太高的定时器你可以这样做:
public static class MySingleTimer
{
public static delegate Notify();
public Notify note;
public static void Timer()
{
while(true)
{
Thread.Sleep(500);
note();
}
}
}
这是个静态类,你可以把任何一个无参数的、返回值为void的函数赋值给note,然后每隔500ms,就会执行一次这个函数。
但是你的系统中只有一个这样的线程。如果你的程序中同时需要多个计时器,每个可能的时间都不相同,执行的函数也不同,这时你可以写成性:
public class MyTimer
{
public delegate Notify();
public note;
public void Timer()
{
while(true)
{
Thread.Sleep(500);
note();
}
}
public void Start()
{
Thread t = new Thread(new ThreadStart(Timer));
t.Start();
}
}
public static Main()
{
MyTimer mt1 = new MyTimer();
mt1.note = SomeFunction1();
MyTimer mt2 = new MyTimer();
mt2.note = SomeFunction2();
}
第一个类代码我没有写线程的声明、初始化和启动的代码。上面这个我写了,因为我看到上面的讨论提到了静态函数、主函数与入口点的问题。以上面的这个为例,非静态的函数、线程是完全可以实现并运行的。
至于你的程序跑飞什么的,首先要说你的描述似乎不太精确。我试试看你的代码。
--------------------编程问答-------------------- 你的二个代码我都在VS2008下调试了,没有出现你说的飞了的情况。mythreadproc无论是第一段代码还是第二段代码均可正常的单步调试。
我估计是其它原因导致的这个结果,你需要再检查有无其它可能导致此类故障的情况。另外多用日志或者DEBUGOUT之类的工具输出程序中的异常。 --------------------编程问答-------------------- 刚才突然想到一个可能的原因,你检查一下看你的主程序是否在工作?
如果你的线程没有设置为background的情况下,按道理主线程中止后这个线程还会运行。由于你是使用的Main()函数中手工创建Form1窗口而不是使用Application.Run(new Fomr1())这样的方式。使用你的这种方式会使主线程在调用完F1.youThread()后立刻中止,从而对其它线程产生影响。 --------------------编程问答-------------------- phy说的不错
看来我对线程和程序运行的机制还是不了解
学习
补充:.NET技术 , C#