当前位置:首页 » 密码管理 » 跨线程访问控件c

跨线程访问控件c

发布时间: 2022-04-26 11:11:41

① C# Timer lock 多线程 的几点疑问。

您好..关于您的问题.
1>
第一个关于Forms.timer的描述正确
System.Windows.Forms.Timer是使用得比较多的Timer,Timer Start之后定时(按设定的Interval)调用挂接在Tick事件上的EvnetHandler。在这种Timer的EventHandler中可 以直接获取和修改UI元素而不会出现问题--因为这种Timer实际上就是在UI线程自身上进行调用的。也正是因为这个原因,导致了在Timer的 EventHandler里面进行长时间的阻塞调用,将会阻塞界面响应的后果。
第二个关于Lock
如果另外的线程并未使用到LOCK的对象.则双方之间没有任何阻塞,中段,等待的关系
2>Lock锁其实指的是以某一个变量为准.
如果你的另外一个线程,使用到了LOCK的对象,那么他会在LOCK代码段内的代码执行完毕后执行.
例如:
Lock(A)
{
//.....耗时10分钟的操作
}
线程B
XXXX
X
XXXX
A=C
XXXXX
如果执行到了A=C
那么下方的代码将不会被执行.当前的运行逻辑等待到了A=C这句话上.
等待LOCK的10分钟操作完毕后.继续执行
所以.如果窗体主线程中有一段代码被 lock ,那么 Forms.Timer会将其中断吗?还是等待这段代码执行完才执行其响应函数。

取决于你锁定了什么
例如你LOCK(THIS)
因为this在winform中指当前窗体,所以你就锁定了所有的THIS内的变量,控件.集体等待.也就是.LOCK会锁定对应变量/对象的继承关系
3>静态的有什么好处,不是静态的有什么影响?

请看第二问的答案.如果你看明白后你就会明白.
如果你LOCK的始终是一个new出来的对象.那么大家其实就等于没有锁.
因为我并没有使用你的对象.所以我不阻塞
4>跨线程调用窗体中的控件会出现线程安全问题,但我发现,跨线程设置状态栏上的 label的文本属性是没有问题的,是 label的特殊,还是状态栏的特殊,还是怎么回事?

状态栏的UI线程其实是他的父线程所属的.
当你要看某个控件是否符合线程 安全的情况.查阅对应对象是否存在INVOKE即可.
其实您的第4个问题我暂时并不敢给您肯定的回答.您的赋值代码我并不清楚.

按照理论来说.他并不特殊.虽然他没有对应invoke.
您用的是STATEXXXXX.LABEL控件吧.
如果还有其他问题.您可以继续追问.

望采纳.
Ths.
Ben.Lampson

② C# 在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级

哈哈,这个问题我也碰到过的!
MSDN上的解释说.NETFramework2.0前的时代可以通过子线程在父线程创建控件,当时你上述的代码是正确的。
但是使用线程操作常常会是复杂而且危险的,所以微软在.NETFramework2.0及以后版本都对线程的操作进行了限制。
像你的代码流程应该是这样的:
首先在form1的窗体载入中新建了一个Class1对象并将本身的引用传递进入其构造函数,然后在Class1的构造函数中创建一个线程。该线程所代理的方法事件是本类中的一个add方法。而add方法的内容则是在form1上放一个textbox.
然而这个流程你需要注意的有几个问题:
1.哪个是主线程?所谓主线程是第一个启动的线程,是从main开始的。form1的这个窗体是由主线程创建的。
2.Thread t的线程是什么?t是由主线程创建的,t的操作内容是在由主线程创建的窗体上放一个textbox.
也就是说,t的操作是跨线程的窗体操作。虽然楼主把 设置成了false,但是还存在在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级这个异常。
这个问题说实话我也不懂,不好说什么。可能微软禁止了一个线程在另一个线程上添加自己的控件,因为这种做法着实不安全。
至于解决办法:
1.不要线程,只在一个主线程中操作。此时你在class1中添加控件也好,在form1中写个方法来添加控件也好,都是可行的。
2.通过代理来实现。在对form1对象的操作中
if(form1.InvokeRequired)
{
form1.Invoke(d);//d为在主线程中创建的代理引用
//d所代理的方法应该是添加控件的内容
}
else
{
form1.Controls.add(textBox1);//直接使用
}
//代码
class Class1
{
Form1 f1;
TextBox textBox1;
delegate void addDelegate();
addDelegate d;
public Class1(Form1 f1)
{
this.f1 = f1;
d=new addDelegate(f1.add());//此处的add是在form1中的方法
Thread t = new Thread(new ThreadStart(add));
t.Start();
}
public void add()
{
if(f1.InvokeRequired)
{
f1.Invoke(d); //使用代理
}
else
{
f1.Controls.add(new TextBox());//...直接调用
}
}
}

楼主可以在MSDN上查找 “线程处理[windows窗体]”,上面有很详细的描述。
在下也是菜鸟一只,有错误请楼下的朋友指出

③ C#内置的几种委托详解,lambda表达式的演变

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 跨线程访问
{
class Program
{
static void Main(string[] args)
{
Action A = delegate
{
Console.WriteLine("I am A ");
};

Action<int> B = delegate(int i)
{
Console.WriteLine("I am B " + i);
};

Action<int, string> C = delegate(int i, string s)
{
Console.WriteLine("I am C " + i + " " + s);
};

Action<int, string, int> D = delegate(int i, string s, int j)
{
Console.WriteLine("I am D " + i + " " + s + " " + j);
};

Action<int, string, int, string> E = delegate(int i, string s, int j, string t)
{
Console.WriteLine("I am E " + i + " " + s + " " + j + " " + t);
};

/*Action A = () =>
{
Console.WriteLine("I'm A ");
};

Action<int> B = (i) =>
{
Console.WriteLine("I'm B " + i);
};

Action<int, string>C = (i, s) =>
{
Console.WriteLine("I'm C " + i + " " + s);
};

Action<int, string, int> D = (i, s, j) =>
{
Console.WriteLine("I'm D " + i + " " + s + " " + j);
};

Action<int, string, int, string> E = (i, s, j, t) =>
{
Console.WriteLine("I'm E " + i + " " + s + " " + j + " " + t);
};*/

A();
B(1);
C(1, "a");
D(1, "a", 2);
E(1, "a", 2, "b");

Console.ReadKey();
}
}
}

我们需要掌握理解好匿名委托,因为,在我们的跨线程访问控件中,一旦我们在非UI线程访问控件就会出错,这是我们利用匿名委托就能解决好问题。

④ VCL中的控件直接支持多线程吗

因为你写的程序是独占模式,而不是应用线程。瑞星杀毒时,点击别的菜单仍然有反应,是因是杀毒过程是另一个线程,WIN 98/NT/2000/XP 是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用CPU 运行时间和资源,或者说,把CPU时间划成片,每个片分给不同的线程,这样,每个线程轮流的“挂起”和“唤醒”,由于时间片很小,给人的感觉是同时运行的。

下面是自己找的一些资料,你参考一下:

多线程带来如下好处:(自己阅读)

1)避免瓶颈;

2)并行操作;

3)提高效率;

在多线程中,通过优先级管理,可以使重要的程序优先操作,提高了

任务管理的灵活性。

另一方面,在多CPU 系统中,可以把不同的线程在不同的CPU 中执行,

真正做到同时处理多任务(Win 98 只是模拟的,而Win/NT/2000是真正的

多CPU同时操作)。

多线程的两个概念:

1) 进程:也称任务,程序载入内存,并分配资源,称为“一个进程

”。注意:进程本身并不一定要正在执行。进程由以下几部分组成:

a>一个私有的地址空间,它是进程可以使用的一组虚拟内存地址空间;

b>程序的相关代码、数据源;

c>系统资源,比如操作系统同步对象等;

d>至少包含一个线程(主线程);

2) 线程:是程序的执行单位(线程本身并不包括程序代码,真正拥

有代码的是进程),每个进程至少包括一个线程,称为主线程,一个进程

如果有多个线程,就可以共享同一进程的资源,并可以并发执行。

线程是进程的一个执行单元,是操作系统分配CPU 时间的基本实体,

线程主要由如下两部分组成:

a>数据结构;

b>CPU 寄存器和堆栈;

一个进程中的线程,可以独立运行,也可以控制另一个线程的运行。

请注意:

多线程不能滥用,书上提到了多线程的几个缺点(自阅)。

2-2 Tthread 对象

虽然Windows 提供了比较多的多线程设计的API 函数,但是直接使用

API 函数一方面极其不方便,而且使用不当还容易出错。为解决这个问题,

Borland 公司率先推出了一种Tthread 对象,来解决多线程设计上的困难,

简化了多线程问题的处理。

应该注意,Tthread 对象是没有实例的,它和界面的交流,主要依靠

主窗体(主VCL线程),这和其他对象使用上有些区别。

一、Tthread 对象的主要方法

构造线程:

constructor Create(CreateSuspended:boolean)

其中:CreateSuspended=true 构造但不唤醒

false 构造的同时即唤醒

也可以用如下方法

inheried Create(CreateSuspended:boolean)

挂起线程:

suspend

(把线程挂起的次数加一)

唤醒线程:

resume

(注意:注意这个属性是把线程挂起的次数减一,当次数为0 时,

即唤醒。也就是说,线程挂起多少次,唤醒也需要多少次。同时挂起

的时候将保持线程的地址指针不变,所以线程挂起后再唤醒,将从挂

起的地方开始运行)

析构(清除线程所占用的内存):

destroy

终止线程(后面会具体讨论):

Terminate

二、线程应用的简单例子:

下面通过一个例子说明上述方法的应用。我们知道,循环是独占

性最强的运行方式之一,现在希望建立两个线程对象,实现循环的并

行运行。具体方法如下:

File---New---Thread Object

这就自动在主Form中建立了一个线程单元(在对话框里写上线程名

字),默认的名字是Unit2。同样方法建立第二个线程单元Unit3。

要注意的是:Unit2和Unit3中有一个给定的过程:

procere Object.Execute;

begin

end;

其中的程序是线程唤醒后自动执行的程序,也可以在里面调用其

他自定义的过程和函数。这个过程的结束,意味着线程程序的结束。

为了构造线程,在interface的Type区,定义一个构造过程:

type

Object = class(TThread) //自动给出的,也可以直接改

private

protected

procere Execute; override;

public

constructor create; //自己写的

并且在implementation区域写上:

constructor Object.create;

begin

inherited create(true);

end

其中Object 为线程对象的名字。所以这么写,是希望在主Form中

调用这个构造过程。

Create()的参数用True,表明构造出的线程为挂起状态。

注意一下,在同一个线程对象里,如果两次构造,将产生两个独立

的线程,不但运行是独立的,而且使用线程的局部变量也是独立的。但

这里为了简化问题,还是建立了两个独立的线程对象,而且两个循环数

是不同的,在并行运算时容易判断出是两个不同的程序在运行。

假定我们给两个线程对象起的名字是:

mymath1

mymath2

这样在Unit1,应该作如下声明:

implementation

uses unit2,unit3;

var thread1:mymath1;

thread2:mymath2;

这样在主线程,将可以通过这两个线程变量调用对应的线程方法。

在主线程区构造线程的方法是:

thread1:=mymath1.create;

thread2:=mymath2.create;

挂起:

thread1.suspend;

thread2.suspend;

唤醒:

thread1.resume;

thread2.resume;

析构:

thread1.destroy;

thread2.destroy;

这里需要说明的是,由于线程单元需要调用Form的Edit控件(对象),

可以采用两种方法:

1) 在线程单元定义一个TEdit对象,例如

edit4:Tedit;

在Execute过程内直接引用

但在Unit1中一定要在FormCreate过程里作一个赋值:

procere TForm1.FormCreate(Sender: TObject);

begin

thread1.edit4:=edit1;

end;

这样,就把第一线程的edit4与Form上的edit1联系来。

2)在第二个线程中首先声明调用Unti1,也就是要加上

Uses Unit1;

这样就可以在该线程单元直接调用主Form的控件了,比如在Unit3中

可以写:

form1.edit2.text:=inttostr(i)

了解了这些基本规则,就可以写出比较复杂的多线程程序了。

还有一点要说明的,默认生成的线程单元,调用的单元只有一个:

Uses Classes;

这样,往往很多函数和对象在线程单元里不能使用,所以在必要时,

应该根据需要User相应的单元,这个例程为了简单,把大部分常用的单

元都拷过去了,这并不是推荐的办法,因为这样一来会使程序的垃圾过

多,所以,一般要用什么拷什么。

三、常用的API 函数

在处理多线程问题的时候,也经常用到Windows提供的API 函数,需

要说明的是,Tthread 对象内部封装的方法,其实主要也是调用API 函

数,但是,考虑更全面,更安全。而直接调用API 函数,往往会因为运

用不当,出现一些不应有的错误。所以,我个人以为,只要用Tthread

对象的方法能解决的,就不要直接调用API 函数,API 函数只应该在用

在Tthread 对象方法解决不了的时候。

例如Tthread 对象方法内部调用API 函数的时候,一般使用推荐的

默认值,但需要更精细的控制时,就可以直接使用API 函数。

其实,Tthread 对象方法已经受到了大多数程序设计者的认可,比

如,原来VB是不具备直接处理多线程的能力的,但是,现在VB.Net就宣

称,它具备了简单处理多线程问题的能力,这就很说明问题。

下面简单介绍几种API 函数,为了清晰方便,这里着重在于说明,

函数正确的描述可以自己阅读书上的例子和手册:

构建线程:

CreateThread(参数1,--安全属性(一般=Nil,默认安全属性)

参数2,--线程堆栈尺寸(一般=0,与主线程相同长

度,而且可以根据需要自动变化)

参数3,--指向函数名指针,@函数名,这个参数十

分重要,不正确将无法调用成功。

参数4,--用户需要向线程传递的参数,是一个指向

结构的指针,不需传递参数时,为Nil。

参数5)--传入与线程有关的一些参数,例如:

CREATE_SUSPENDED 创建一个挂起的线程;

0 创建后立即激活。

书上有这个函数应用的十分清晰的例子,可以自己阅读。

一般并不推荐使用 CreateTheard函数,而推荐使用RTL 库里的

System单元中定义的 BeginTheard函数,因为这除了能创建一个线程

和一个入口函数以外,还增加了几项保护措施,具体的请参阅书上的

第10页说明。

对应suspend(挂起)和resume(唤醒)的两个API 函数为:

Function SuspendThread(hThread:Thandle):DWORD;

Function ResumeThread(hThread:Thandle):DWORD;

其中,Thandle被要求控制线程的句柄,函数调用成功,返回挂

起的次数,调用不成功。则返回0xFFFFFFFF。

四、线程的终止和退出:

1)自动退出:

一个线程从Execute()过程中退出,即意味着线程的终止,此时

将调用Windows的ExitThread()函数来清除线程所占用的堆栈。

如果线程对象的 FreeOnTerminate 属性设为True,则线程对象

将自动删除,并释放线程所占用的资源。

这是消除线程对象最简单的办法。

2)受控退出:

利用线程对象的Terminate属性,可以由进程或者由其他线程控

制线程的退出。只需要简单的调用该线程的Terminate方法,并设直

线程对象的Terminate属性为True。

在线程中,应该不断监视Terminate的值,一旦发现为True,则

退出,例如在Execute()过程中可以这样写:

While not Terminate do

begin

........

end;

3)退出的API 函数:

关于线程退出的API 函数声明如下:code

Function TerminateThread(hThread:Thandle;dwExitCode:DWORD);

不过,这个函数会使代码立刻终止,而不管程序中有没有

try....finally

机制,可能会导致错误,不到万不得已,最好不要使用。

4) 利用挂起线程的方法(suspend)

利用挂起线程的suspend方法,后面跟个Free,也可以释放线程,

例如:

thread1.suspend; //挂起

thread2.free; //释放

书上有相应的例子。

五、 线程的优先级:

在多线程的情况下,一般要根据线程执行任务的重要性,给线程

适当的优先级,一般如果量的线程同时申请CPU 时间,优先级高的线

程优先。

在Windows下,给线程的优先级分为30级,而Delphi中Tthread

对象相对简单的把优先级分为七级。也就是在Tthread中声明了一个

枚举类型TTthreadPriority:

type

TTthreadPriority(tpidle,tpLowest,tpLower,tpNormal,

tpHight,tpHighest,tpTimecrital)

分别对应的是最低(系统空闲时有效,-15),较低(-2),低

(-1),正常(普通0),高(1),较高(2),最高(15)。

其中tpidle和tpTimecrital有些特殊,具体情况请阅读书上有

关内容。

设置优先级可使用thread对象的priority属性:

threadObject.priority:=Tthreadpriority(级别);

这里给出了一个演示多线程优先级的实例:

2-3 在数据库中使用多线程

一)使用ADO模式

由于Delphi 6.0的ADO 数据源控件内置了多线程能力,所以,在

ADO模式下,使用多线程不需要做更多的工作。用两个ADOTable控件,

分别连到两个数据库,并且分别通过DataSource控件,与数据帮定控

件联系就可以了,这样就可以实现前后台处理数据库问题。

二)使用BDE模式和Tseeion对象

如果需要使用BDE 模式,那么多线程使用数据库,就要考虑Session

的问题。在单线程时,每个数据源的建立就自动生成一个Session,

这是这个数据源私有的关于数据库信息的文件。但多线程时,必须统

一管理,所以在BDE 中专门提供了一个Tsession对象,它可以同时管理

不同的Databas数据源对象。

Databas数据源可以接受来自不同数据平台的数据库。

数据库1---databas(2)----table(Qurey)(3)---datasource

| |

| |

|--------- Tsession(1)

| |

| |

数据库2---databas(2)----table(Qurey)(3)---datasource

方法:

1)Tsession

属性:SessionName=名(自起)

Active=true (激活)

2)Database(可以有多个)

属性:SessionName=Tsession名

Dataname=名(自起,作为Table的标识)

AliasName=数据库别名

Connected=True (激活)

3)Table或Qurey

属性:SessionName=Tsession名(不要用默认值)

DatabaseName=如果前面起了名,这里就会出现Database

的名字。

Tablename=表名

Active=true (激活)

以后比如加入Datasoucre和其他一样,这样就可以构造两个前后

台处理的数据库管理系统了。

2-4 多线程的同步机制

同步机制,实际上是事件驱动机制,意思是让线程平时处于“休

眠”状态,除非发生某个事件才触发。

例如一个拷贝文件,拷贝线程完成一个程序块后,再唤醒进程条

线程做一个格的填充。

研究多线程的同步机制的必要性在于,多线程同步工作时,如果

同时调用相同的资源,就可能会出现问题,一般读出是不会有问题的,

但是,如果写入(全局变量、数据库),就会发生冲突,甚至产生死

锁和竞争问题。

一、使用Synchronize方法

这个方法用于访问VCL 主线程所管理的资源,其方法的应用是:

第一步:把访问主窗口(或主窗口控件资源)的代码放到线程的

一个方法中;

第二步:是在线程对象的Execute方法中,通过Synchronize方法

使用该方法。

实例:

procere Theater.Execute;

begin

Synchronize(update);

end;

procere Theater.update;

begin

.........

end;

这里通过 Synchronize使线程方法update同步。

二、使用VCL类的Look方法

在Delphi的IDE提供的构件中,有一些对象内部提供了线程的同

步机制,工作线程可以直接使用这些控件,比如:Tfont,Tpen,

TBitmap,TMetafile,Ticon等。另外,一个很重要的控件对象叫

TCanvas,提供了一个Lock方法用于线程的同步,当一个线程使用此

控件对象的时候,首先调用这个对象的Lock方法,然后对这个控件

进行操作,完毕后再调用Unlock方法,释放对控间的控制权。

例如:

CanversObject.look;

try

画图

finally

CanversObject.unlock;

end;

{使用这个保护机制,保证不论有没有异常,unlock都会被执行

否则很可能会发生死锁。在多线程设计的时候,应该很注意发生死

锁的问题}

三、Waitfor方法

当一个线程应该等待另一个线程结束时,可以调用Waitfor方法。

这个方法属于等待线程对象,Waitfor方法的原型如下:

Function Waitfor(Const Astring:string):string;

比如在前面最基本的线程的例子中,唤醒线程的语句中加上

thread1.resume;

thread1.waitfor;

thread2.resume;

那么所有的线程都必须等待thread1运行完毕后才能运行,其中

包括主线程,可以预想,由于thread1调用了主窗体的Edit控件,那

么,在thread1运行中间,Edie1也不会显示。

这就告诉我们,这样的代码是不能作为主线程的一部分的,如果

与主窗体连接的线程内等待另一个线程结束,而另一个线程又要等待

访问用户界面,就可能是程序陷于死锁。

这点在应用的时候要谨慎。

⑤ 非UI线程中如何改变UI控件属性

在.NET中如需在非UI线程中改变UI控件属性时,CLR会抛出异常,提示无法在非UI线程中更新界面上的控件(Cross-thread operation not valid)。一般情况下有两种解决办法。第一种就是设置Control的静态属性为False,如下:publicForm1(){
InitializeComponent();
Control.=false;}privatevoidbutton1_Click(objectsender, EventArgs e){
Thread thread=newThread(()={for(inti=0; i<100000; i++){
label1.Text=
i.ToString();
label1.Refresh();}});
thread.Start();}
另一种办法,就是使用委托,根据控件的InvokeRequired属性判断当前控件的更新操作是否是在另一个线程中。如果是,
则使用委托进行方法调用并更新控件。但是这种方法有个缺点,就是需要针对每个控件的属性设置方式创建一些单独的委托和方法,这些委托和方法仅仅是在解决跨线程操作的时候使用。比如,你在另一个线程中需要修改某个label的text时,你就需要创建一个SetLabelText方法,假设你还需要更新TextBox的text,那么你还需要另外创建一个SetTextBoxText方法。
通过下面的委托和方法的定义,我们实现了一次定义,多次使用。请看:(paramsobject[] args);(Component c,
ParameterizedControlUpdate callback,paramsobject[] args);(Component c,
ParameterizedControlUpdate callback,paramsobject[] args){
Control target=(cisControl)?(casControl) :this;if(target.InvokeRequired){
ControlUpdateDelegate d=DelegatedControlUpdate;
target.Invoke(d,
newobject[] { c, callback, args });}else{
callback(args);}}
于是,上面的例子可以改为:privatevoidbutton1_Click(objectsender, EventArgs e){
Thread thread=newThread(()={for(inti=0; i<100000; i++){
DelegatedControlUpdate(label1, args={
label1.Text=(string)args[0];
label1.Refresh();

⑥ vc多线程参数传递问题

可以这样做:
为线程参数定义一个结构体
struct threadParam
{
HANDLE* self;
HANDLE* other;
//还可以定义一些其他你认为需要的参数
};

//假设有2个线程A、B
HANDLE *HA = new HANDLE;
HANDLE *HB = new HANDLE;

threadParam *pA = new threadParam;
PA->self = HA;
PA->other = HB;

*HA = createthread(NULL,funcA,PA,....);

将PA做为参数传递给线程A。这样就可以在线程函数里通过指针使用a,b的线程句柄了。
同样创建b线程的时候这样做一遍就ok。

不知道这样说明白否?

⑦ C#中如何从指定文件中一秒钟读取一行数据,要用线程

public void ReadTest(string filename)
{
Thread readthread = new Thread(new ParameterizedThreadStart(Read));
readthread.Start("c:\\1.txt");
}

public void Read(object file)
{
string fileurl = file as string;
StreamReader sr = new StreamReader(fileurl);
string result;
while (true)
{
result = sr.ReadLine();
if (result == null)
break;
textbox1.append(result);
Thread.Sleep(1000);
}
sr.Close();
}

以上代码你在调试下会出现 无法跨线程 调用控件的异常。你可以不用管它,你直接运行Debug下的exe,是可以运行的。原因是显示控件和处理消息队列是系统调用了GUI线程,你在调试的情况下调试环境是不允许你跨线程调用GUI线程(Main方法的主线程除外),所以运行程序的时候要直接运行Debug下的exe。
当然,你也可以利用Control. = false; 加入这句代码在Thread readthread = new Thread(new ParameterizedThreadStart(Read));
之前
调试时也不会提示出错,可以正常执行上面的程序。

⑧ 线程、进程在跨线程(进程)访问内存,权限有什么不同


说法一:进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行

说法二:进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于:

简而言之,一个程序至少有一个进程,一个进程至少有一个线程.

线程的划分尺度小于进程,使得多线程程序的并发性高。

另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

说法三:多线程共存于应用程序中是现代操作系统中的基本特征和重要标志。用过UNIX操作系统的读者知道进程,在UNIX操作系统中,每个应用程序的执行都在操作系统内核中登记一个进程标志,操作系统根据分配的标志对应用程序的执行进行调度和系统资源分配,但进程和线程有什么区别呢?

进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于:

线程的划分尺度小于进程,使得多线程程序的并发性搞。

另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

进程(Process)是最初定义在Unix等多用户、多任务操作系统环境下用于表示应用程序在内存环境中基本执行单元的概念。以Unix操作系统为例,进程是Unix操作系统环境中的基本成分、是系统资源分配的基本单位。Unix操作系统中完成的几乎所有用户管理和资源分配等工作都是通过操作系统对应用程序进程的控制来实现的。

C、C++、Java等语言编写的源程序经相应的编译器编译成可执行文件后,提交给计算机处理器运行。这时,处在可执行状态中的应用程序称为进程。从用户角度来看,进程是应用程序的一个执行过程。从操作系统核心角度来看,进程代表的是操作系统分配的内存、CPU时间片等资源的基本单位,是为正在运行的程序提供的运行环境。进程与应用程序的区别在于应用程序作为一个静态文件存储在计算机系统的硬盘等存储空间中,而进程则是处于动态条件下由操作系统维护的系统资源管理实体。多任务环境下应用程序进程的主要特点包括:

●进程在执行过程中有内存单元的初始入口点,并且进程存活过程中始终拥有独立的内存地址空间;

●进程的生存期状态包括创建、就绪、运行、阻塞和死亡等类型;

●从应用程序进程在执行过程中向CPU发出的运行指令形式不同,可以将进程的状态分为用户态和核心态。处于用户态下的进程执行的是应用程序指令、处于核心态下的应用程序进程执行的是操作系统指令。

在Unix操作系统启动过程中,系统自动创建swapper、init等系统进程,用于管理内存资源以及对用户进程进行调度等。在Unix环境下无论是由操作系统创建的进程还要由应用程序执行创建的进程,均拥有唯一的进程标识(PID)。

说法四:应用程序在执行过程中存在一个内存空间的初始入口点地址、一个程序执行过程中的代码执行序列以及用于标识进程结束的内存出口点地址,在进程执行过程中的每一时间点均有唯一的处理器指令与内存单元地址相对应。

Java语言中定义的线程(Thread)同样包括一个内存入口点地址、一个出口点地址以及能够顺序执行的代码序列。但是进程与线程的重要区别在于线程不能够单独执行,它必须运行在处于活动状态的应用程序进程中,因此可以定义线程是程序内部的具有并发性的顺序代码流。

Unix操作系统和Microsoft Windows操作系统支持多用户、多进程的并发执行,而Java语言支持应用程序进程内部的多个执行线程的并发执行。多线程的意义在于一个应用程序的多个逻辑单元可以并发地执行。但是多线程并不意味着多个用户进程在执行,操作系统也不把每个线程作为独立的进程来分配独立的系统资源。进程可以创建其子进程,子进程与父进程拥有不同的可执行代码和数据内存空间。而在用于代表应用程序的进程中多个线程共享数据内存空间,但保持每个线程拥有独立的执行堆栈和程序执行上下文(Context)。

基于上述区别,线程也可以称为轻型进程 (Light Weight Process,LWP)。不同线程间允许任务协作和数据交换,使得在计算机系统资源消耗等方面非常廉价。

线程需要操作系统的支持,不是所有类型的计算机都支持多线程应用程序。Java程序设计语言将线程支持与语言运行环境结合在一起,提供了多任务并发执行的能力。这就好比一个人在处理家务的过程中,将衣服放到洗衣机中自动洗涤后将大米放在电饭锅里,然后开始做菜。等菜做好了,饭熟了同时衣服也洗好了。

需要注意的是:在应用程序中使用多线程不会增加 CPU 的数据处理能力。只有在多CPU 的计算机或者在网络计算体系结构下,将Java程序划分为多个并发执行线程后,同时启动多个线程运行,使不同的线程运行在基于不同处理器的Java虚拟机中,才能提高应用程序的执行效率。

⑨ unity c#跨线程调用怎么实现

在unity里边使用多线程做一些事情是非常好的,比如解压资源 更新资源等。因为单开线程的话 不会影响主线程卡顿,这样UI就不会卡了。但是开的线程里边不能执行unity主线程的mono代码。线程启动后,执行完毕自动结束该线程、可以同时启动多个线程做事。
代码如下: using System.Threading;
void StartThread()
{

Thread athread = new Thread(new ThreadStart(goThread));
athread.IsBackground = true;//防止后台现成。相反需要后台线程就设为false

athread.Start();
}
void Awake()
{
StartThread();
}
object lockd = new object();
void goThread()
{
int index = 0;
while (true)
{
lock (lockd)//防止其他线程访问当前线程使用的数据
{
Debug.Log("in thread" + index);
index++;
if (index == 100)
{
Thread.Sleep(10000);// 将当前线程挂起指定的时间 毫秒 时间结束后 继续执行下一步 和yield类似
}
else if (index == 200)
{
break;//该函数执行完自动结束该线程
}
}
}
}

所以其实多线程和协程原理差别很大的,只是功能有点类似。

1、当在主线程中创建了一个线程,那么该线程的IsBackground默认是设置为FALSE的。
2、当主线程退出的时候,IsBackground=FALSE的线程还会继续执行下去,直到线程执行结束。
3、只有IsBackground=TRUE的线程才会随着主线程的退出而退出
---------------------------------------------------------------------------------------------

ThreadStart:
Thread athread = new Thread(new ThreadStart(goThread));
athread.Start();//该方法启动的多线程 不能带有参数。

ParameterThreadStart:

ParameterThreadStart的定义为void ParameterizedThreadStart(object state),使用这个这个委托定义的线程的启动函数可以接受一个输入参数,具体例子如下 :
[csharp] view plain
ParameterizedThreadStart threadStart=new ParameterizedThreadStart(Calculate)
Thread thread=new Thread() ;
thread.Start(0.9);//参数是0.9
public void Calculate(object arg)//arg参数是0.9
{
double Diameter=double(arg);
Console.Write("The Area Of Circle with a Diameter of {0} is {1}"Diameter,Diameter*Math.PI);
}
Calculate方法只有一个为object类型的参数。需要传多个参数的时候 需要把参数都塞进object 然后进行转换。比如:

一个参数 void BuildA(object para){ List<int> list=para as List<int>;...}
BuildA(list);
多个参数 void BuildB(object para){ object[] ps= para as object[];List<int> list=ps[0] as as List<int>;GameObject b=ps[1] as GameObject;...}
BuildB(new object[]{list,obj});//把多个参数塞到object数组里边 传过去,相当于只传一个参数。

至于是开一个线程还是多个线程 根据需求和内核数SystemInfo.processorCount来确定。最好一个核开一个线程 会快点。
详见bundleglobal.cs和sdFileSystem.cs/sdMultiThread.cs

⑩ 请教c#多线程操作更新控件的简便方法

char*c[]={"ENTER","NEW","POIT","FIRST"};//指针数组,数组的每个元素是指针,这里存常量字符串的首地址。char**cp[]={c+3,c+2,c+1,c};//二级指针数组,数组每个元素是二级指针,这里存了c[3].c[2],c[1],c[0]的地址,也就是上面字符串顺序逆序char***cpp=cp;三级指针指向cp数组首地址。ps,一般三级指针在正常的程序里不会出现,容易形成非常混乱的局面。printf("%s\n",**++cpp);POIT//优先级相同,临近原则++cpp--->c+2的地址,两次间址是POITprintf("%s\n,",*--*++cpp);ENTER//++cpp--->cp+1(上面自增过了),间址一次变成cp[1],--c+1再间地址,就是c第一个元素。ENTER。printf("%s\n",*cpp[-2]+3);ST//cpp指向c+1的位置。cpp[-2]就是*(cpp-2)指向cp+0,就是c+3*(c+3)+3不就是FIRST数第四个字母么,后面输出ST。printf("%s\n",cpp[-1][-1]+1);上面cpp还是指向在c+1,*(cpp-1)是c+2,*(*c+2-1)--->c+1,NEW这个单词地址,*((*(c+1))+1)数到E往后输出}

热点内容
客户数据库建立 发布:2025-07-21 14:13:20 浏览:302
linux组中删除用户 发布:2025-07-21 14:10:21 浏览:48
天龙八部免费脚本下载 发布:2025-07-21 13:54:44 浏览:396
x型压缩机 发布:2025-07-21 13:53:00 浏览:934
oracle存储过程视频 发布:2025-07-21 13:46:29 浏览:846
安卓没有sd卡怎么升级 发布:2025-07-21 13:45:49 浏览:891
南京编程高考 发布:2025-07-21 13:27:52 浏览:526
数码编程下载 发布:2025-07-21 13:27:51 浏览:314
金字塔c语言 发布:2025-07-21 13:23:34 浏览:641
装备数据库 发布:2025-07-21 13:14:24 浏览:844