分享
 
 
 

在.NET中的线程处理(4)

王朝c#·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Timer [C#]

计时器是使您能够指定要在指定时间调用的委托的轻量对象。线程池中的线程执行等待操作。

使用 Timer 类是非常简单的。需要创建一个 Timer(通过将 TimerCallback 委托传递到回调方法)、一个表示将被传递给回调的状态的对象、初始引发时间以及表示回调调用之间的时间段的时间。若要取消挂起的计时器,请调用 Timer.Dispose 函数。

注意 还有 System.Windows.Forms.Timer 类。该类是基于操作系统计时器支持的,如果您没有在线程上发送消息,则计时器将不会出现。这就使得 System.Threading.Timer 在许多情况下更为有用。

下面的简单代码示例说明了 Timer 的使用。

[Visual Basic]

Imports System

Imports System.Threading

Imports Microsoft.VisualBasic

Public Class TimerTest

Public timerevent As ManualResetEvent

Public Sub New()

timerevent = New ManualResetEvent(False)

Dim timer As New Timer(New TimerCallback(AddressOf Me.TimerMethod), Nothing, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5))

Dim TickTimer As New Timer(New TimerCallback(AddressOf Me.Tick), Nothing, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1))

End Sub 'New

Public Sub TimerMethod(state As Object)

Console.WriteLine(ControlChars.Cr + "The Timer invoked this method.")

timerevent.Set()

End Sub 'TimerMethod

Public Sub Tick(state As Object)

Console.Write(".")

End Sub 'Tick

Public Shared Sub Main()

Dim test As New TimerTest()

Console.WriteLine("The timer has started and will count for five seconds.")

test.timerevent.WaitOne()

Console.WriteLine("...and control returned to the primary thread.")

End Sub 'Main

End Class 'TimerTest

[C#]

using System;

using System.Threading;

public class TimerTest{

public ManualResetEvent timerevent;

public TimerTest(){

timerevent = new ManualResetEvent(false);

Timer timer = new Timer(

new TimerCallback(this.TimerMethod),

null,

TimeSpan.FromSeconds(5),

TimeSpan.FromSeconds(5)

);

Timer TickTimer = new Timer(

new TimerCallback(this.Tick),

null,

TimeSpan.FromSeconds(1),

TimeSpan.FromSeconds(1)

);

}

public void TimerMethod(object state){

Console.WriteLine("\rThe Timer invoked this method.");

timerevent.Set();

}

public void Tick(object state){

Console.Write(".");

}

public static void Main(){

TimerTest test = new TimerTest();

Console.WriteLine("The timer has started and will count for five seconds.");

test.timerevent.WaitOne();

Console.WriteLine("...and control returned to the primary thread.");

}

}

Monitor [C#]

Monitor 对象通过使用 Monitor.Enter、Monitor.TryEnter 和 Monitor.Exit 方法对特定对象获取锁和释放锁来公开同步访问代码区域的能力。在对代码区域获取锁后,就可以使用 Monitor.Wait、Monitor.Pulse 和 Monitor.PulseAll 方法了。如果锁被暂挂,则 Wait 释放该锁并等待通知。当 Wait 接到通知后,它将返回并再次获取该锁。Pulse 和 PulseAll 都会发出信号以便等待队列中的下一个线程继续执行。

注意到 Monitor 和 WaitHandle 对象在使用上的区别是非常重要的。Monitor 对象是完全托管、完全可移植的,并且在操作系统资源要求方面可能更为有效。WaitHandle 对象表示操作系统可等待对象,对于在托管和非托管代码之间进行同步非常有用,并公开一些高级操作系统功能(如同时等待许多对象的能力)。

下面的代码示例说明了 Monitor 类(用编译器关键字实现)和 Interlocked 类的结合使用。

[Visual Basic]

Imports System

Imports System.Threading

Imports Microsoft.VisualBasic

' Note: The class whose internal public member is the synchronizing method

' is not public; none of the client code takes a lock on the Resource object.

' The member of the nonpublic class takes the lock on itself. Written this

' way, malicious code cannot take a lock on a public object.

Class SyncResource

Public Sub Access(threadNum As Int32)

' Uses Monitor class to enforce synchronization.

SyncLock Me

' Synchronized: Despite the next conditional, each thread waits on its predecessor.

If threadNum Mod 2 = 0 Then

Thread.Sleep(2000)

End If

Console.WriteLine("Start Synched Resource access (Thread={0})", threadNum)

Thread.Sleep(200)

Console.WriteLine("Stop Synched Resource access (Thread={0})", threadNum)

End SyncLock

End Sub 'Access

End Class 'SyncResource

' Without the lock, the method is called in the order in which threads reach it.

Class UnSyncResource

Public Sub Access(threadNum As Int32)

' Does not use Monitor class to enforce synchronization.

' The next call throws the thread order.

If threadNum Mod 2 = 0 Then

Thread.Sleep(2000)

End If

Console.WriteLine("Start UnSynched Resource access (Thread={0})", threadNum)

Thread.Sleep(200)

Console.WriteLine("Stop UnSynched Resource access (Thread={0})", threadNum)

End Sub 'Access

End Class 'UnSyncResource

Public Class App

Private Shared numAsyncOps As Int32 = 5

Private Shared asyncOpsAreDone As New AutoResetEvent(False)

Private Shared SyncRes As New SyncResource()

Private Shared UnSyncRes As New UnSyncResource()

Private Shared threadNum As Int32

Public Shared Sub Main()

For threadNum = 0 To 4

ThreadPool.QueueUserWorkItem(AddressOf SyncUpdateResource, threadNum)

Next threadNum

' Wait until this WaitHandle is signaled.

asyncOpsAreDone.WaitOne()

Console.WriteLine(ControlChars.Tab + ControlChars.Lf + "All synchronized operations have completed." + ControlChars.Lf)

' Reset the thread count for unsynchronized calls.

numAsyncOps = 5

For threadNum = 0 To 4

ThreadPool.QueueUserWorkItem(AddressOf UnSyncUpdateResource, threadNum)

Next threadNum

' Wait until this WaitHandle is signaled.

asyncOpsAreDone.WaitOne()

Console.WriteLine(ControlChars.Tab + ControlChars.Cr + "All unsynchronized thread operations have completed.")

End Sub 'Main

' The callback method's signature MUST match that of a System.Threading.TimerCallback

' delegate (it takes an Object parameter and returns void).

Shared Sub SyncUpdateResource(state As Object)

' This calls the internal synchronized method, passing a thread number.

SyncRes.Access(CType(state, Int32))

' Count down the number of methods that the threads have called.

' This must be synchronized, however; you cannot know which thread will

' access the value **before** another thread's incremented value has been

' stored into the variable.

If Interlocked.Decrement(numAsyncOps) = 0 Then

asyncOpsAreDone.Set()

' Announce to Main that in fact all thread calls are done.

End If

End Sub 'SyncUpdateResource

' The callback method's signature MUST match that of a System.Threading.TimerCallback

' delegate (it takes an Object parameter and returns void).

Shared Sub UnSyncUpdateResource(state As [Object])

' This calls the internal synchronized method, passing a thread number.

UnSyncRes.Access(CType(state, Int32))

' Count down the number of methods that the threads have called.

' This must be synchronized, however; you cannot know which thread will

' access the value **before** another thread's incremented value has been

' stored into the variable.

If Interlocked.Decrement(numAsyncOps) = 0 Then

asyncOpsAreDone.Set()

' Announce to Main that in fact all thread calls are done.

End If

End Sub 'UnSyncUpdateResource

End Class 'App

[C#]

using System;

using System.Threading;

// Note: The class whose internal public member is the synchronizing method

// is not public; none of the client code takes a lock on the Resource object.

// The member of the nonpublic class takes the lock on itself. Written this

// way, malicious code cannot take a lock on a public object.

class SyncResource {

public void Access(Int32 threadNum) {

// Uses Monitor class to enforce synchronization.

lock (this) {

// Synchronized: Despite the next conditional, each thread waits on its predecessor.

if (threadNum % 2 == 0)

Thread.Sleep(2000);

Console.WriteLine("Start Synched Resource access (Thread={0})", threadNum);

Thread.Sleep(200);

Console.WriteLine("Stop Synched Resource access (Thread={0})", threadNum);

}

}

}

// Without the lock, the method is called in the order in which threads reach it.

class UnSyncResource {

public void Access(Int32 threadNum) {

// Does not use Monitor class to enforce synchronization.

// The next call throws the thread order.

if (threadNum % 2 == 0)

Thread.Sleep(2000);

Console.WriteLine("Start UnSynched Resource access (Thread={0})", threadNum);

Thread.Sleep(200);

Console.WriteLine("Stop UnSynched Resource access (Thread={0})", threadNum);

}

}

public class App {

static Int32 numAsyncOps = 5;

static AutoResetEvent asyncOpsAreDone = new AutoResetEvent(false);

static SyncResource SyncRes = new SyncResource();

static UnSyncResource UnSyncRes = new UnSyncResource();

public static void Main() {

for (Int32 threadNum = 0; threadNum < 5; threadNum++) {

ThreadPool.QueueUserWorkItem(new WaitCallback(SyncUpdateResource), threadNum);

}

// Wait until this WaitHandle is signaled.

asyncOpsAreDone.WaitOne();

Console.WriteLine("\t\nAll synchronized operations have completed.\t\n");

// Reset the thread count for unsynchronized calls.

numAsyncOps = 5;

for (Int32 threadNum = 0; threadNum < 5; threadNum++) {

ThreadPool.QueueUserWorkItem(new WaitCallback(UnSyncUpdateResource), threadNum);

}

// Wait until this WaitHandle is signaled.

asyncOpsAreDone.WaitOne();

Console.WriteLine("\t\nAll unsynchronized thread operations have completed.");

}

// The callback method's signature MUST match that of a System.Threading.TimerCallback

// delegate (it takes an Object parameter and returns void).

static void SyncUpdateResource(Object state) {

// This calls the internal synchronized method, passing a thread number.

SyncRes.Access((Int32) state);

// Count down the number of methods that the threads have called.

// This must be synchronized, however; you cannot know which thread will

// access the value **before** another thread's incremented value has been

// stored into the variable.

if (Interlocked.Decrement(ref numAsyncOps) == 0)

asyncOpsAreDone.Set();

// Announce to Main that in fact all thread calls are done.

}

// The callback method's signature MUST match that of a System.Threading.TimerCallback

// delegate (it takes an Object parameter and returns void).

static void UnSyncUpdateResource(Object state) {

// This calls the internal synchronized method, passing a thread number.

UnSyncRes.Access((Int32) state);

// Count down the number of methods that the threads have called.

// This must be synchronized, however; you cannot know which thread will

// access the value **before** another thread's incremented value has been

// stored into the variable.

if (Interlocked.Decrement(ref numAsyncOps) == 0)

asyncOpsAreDone.Set();

// Announce to Main that in fact all thread calls are done.

}

}

WaitHandle

WaitHandle 类封装 Win32 同步句柄,并用于表示运行库中所有允许执行多个等待操作的同步对象。需要注意的是,虽然 WaitHandle 对象表示操作系统同步对象并因此而公开高级功能,但它们还是不如 Monitor 的可移植性好;Monitor 是完全托管的,某些情况下在使用操作系统资源方面更为有效。

ManualResetEvent

使用 ManualResetEvent 类使某个线程等待,直到某个事件通过调用 ManualResetEvent.Set 将其置于已发信号的状态为止。ManualResetEvent 将始终保持已发信号的状态,直到通过 Reset 方法将其显式设置为未发信号的状态为止。对于任何数目的等待线程或随后通过调用一个等待函数开始等待指定的事件对象的操作的线程,它们都可以在该对象处于已发信号的状态时被释放。ManualResetEvent 与 Win32 CreateEvent 调用相对应,并将 bManualReset 参数指定为 true。

AutoResetEvent

使用 AutoResetEvent 类可以使某个线程等待,直到某个事件通过调用 AutoResetEvent.Set 将其置于已发信号的状态为止。与 ManualResetEvent 不同,AutoResetEvent 在单个等待线程被释放后由系统自动重置为未发信号的状态。如果没有任何线程正在等待,则该事件对象的状态将保持已发信号的状态。AutoResetEvent 与 Win32 CreateEvent 调用相对应,并将 bManualReset 参数指定为 false。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有