⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 threadex.cs

📁 蓝牙通讯
💻 CS
字号:
//==========================================================================================
//
//		OpenNETCF.Threading.ThreadEx
//		Copyright (c) 2004, OpenNETCF.org
//
//		This library is free software; you can redistribute it and/or modify it under 
//		the terms of the OpenNETCF.org Shared Source License.
//
//		This library is distributed in the hope that it will be useful, but 
//		WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
//		FITNESS FOR A PARTICULAR PURPOSE. See the OpenNETCF.org Shared Source License 
//		for more details.
//
//		You should have received a copy of the OpenNETCF.org Shared Source License 
//		along with this library; if not, email licensing@opennetcf.org to request a copy.
//
//		If you wish to contact the OpenNETCF Advisory Board to discuss licensing, please 
//		email licensing@opennetcf.org.
//
//		For general enquiries, email enquiries@opennetcf.org or visit our website at:
//		http://www.opennetcf.org
//
//==========================================================================================

using System;
using System.Threading;
using System.Runtime.InteropServices;
using System.Reflection;
using OpenNETCF.Win32;

namespace OpenNETCF.Threading
{
	/// <summary>
	/// Creates and controls a thread, sets its priority, and gets its status.
	/// <para><b>New in v1.1</b></para>
	/// </summary>
	public class ThreadEx
	{
		Thread				m_thread;
		ThreadStart			m_start;
		IntPtr				m_handle;
		IntPtr				m_terminationEvent;
		string				m_name;
		ThreadState			m_state;

		#region static methods
		// these method maintain the Microsoft Thread interface so users don't have to use both Thread classes

		/// <summary>
		/// Blocks the current thread for the specified number of milliseconds.
		/// </summary>
		/// <param name="millisecondsTimeout">Amount of time to block</param>
		public static void Sleep(int millisecondsTimeout)
		{
			Thread.Sleep(millisecondsTimeout);
		}

		/// <summary>
		/// Blocks the current thread for the specified span of time.
		/// </summary>
		/// <param name="timeout">Amount of time to block</param>
		public static void Sleep(TimeSpan timeout)
		{
			Sleep(Convert.ToInt32(timeout.TotalMilliseconds));
		}
		
		/// <summary>
		/// Allocates an unnamed data slot on all the threads.
		/// </summary>
		/// <returns>A <see cref="LocalDataStoreSlot"/>.</returns>
		public static System.LocalDataStoreSlot AllocateDataSlot()
		{
			return Thread.AllocateDataSlot();
		}

		/// <summary>
		/// Allocates a named data slot on all threads.
		/// </summary>
		/// <param name="name">The name of the data slot to be allocated.</param>
		/// <returns>A <see cref="LocalDataStoreSlot"/>.</returns>
		public static System.LocalDataStoreSlot AllocateNamedDataSlot(string name)
		{
			return Thread.AllocateNamedDataSlot(name);
		}

		/// <summary>
		/// Eliminates the association between a name and a slot, for all threads in the process.
		/// </summary>
		/// <param name="name">The name of the data slot to be freed.</param>
		public static void FreeNamedDataSlot(string name)
		{
			Thread.FreeNamedDataSlot(name);
		}

		/// <summary>
		/// Retrieves the value from the specified slot on the current thread.
		/// </summary>
		/// <param name="slot">The <see cref="LocalDataStoreSlot"/> from which to get the value.</param>
		/// <returns>The value retrieved</returns>
		public static object GetData(LocalDataStoreSlot slot)
		{
			return Thread.GetData(slot);
		}

		/// <summary>
		/// Looks up a named data slot.
		/// </summary>
		/// <param name="name">The name of the local data slot.</param>
		/// <returns>A <see cref="LocalDataStoreSlot"/> allocated for this thread.</returns>
		public static System.LocalDataStoreSlot GetNamedDataSlot(string name)
		{
			return Thread.GetNamedDataSlot(name);
		}

		/// <summary>
		/// Sets the data in the specified slot on the currently running thread, for that thread's current domain.
		/// </summary>
		/// <param name="slot">The <see cref="LocalDataStoreSlot"/> in which to set the value.</param>
		/// <param name="data">The value to be set.</param>
		public static void SetData(LocalDataStoreSlot slot, object data)
		{
			Thread.SetData(slot, data);
		}
		#endregion

		#region Properties
		/// <summary>
		/// Gets or sets the name of the thread.
		/// </summary>
		/// <value>A string containing the name of the thread, or a null reference (Nothing in Visual Basic) if no name was set.</value>
		public string Name
		{
			get { return m_name; }
			set
			{
				if(m_name != null)
					throw new InvalidOperationException("Thread Name already set");

				m_name = value;
			}
		}

		/// <summary>
		/// Gets a value indicating the execution status of the current thread.
		/// </summary>
		/// <value><b>true</b> if this thread has been started and has not terminated normally or aborted; otherwise, <b>false</b>.</value>
		public bool IsAlive
		{
			get
			{ 
				if((m_state == ThreadState.Stopped)	| (m_state == ThreadState.Unstarted))
					return false;

				return true;
			}
		}

		/// <summary>
		/// Gets or sets a value indicating the scheduling priority of a thread.
		/// </summary>
		/// <value>One of the <see cref="System.Threading.ThreadPriority"/> values. The default value is Normal.</value>
		public System.Threading.ThreadPriority Priority
		{
			get{ return m_thread.Priority; }
			set
			{ 
				if(m_state == ThreadState.Stopped)
					throw new ThreadStateException();

				m_thread.Priority = value; 
			}
		}

		/// <summary>
		/// Returns the ThreadEx instance's current <see cref="ThreadState"/>
		/// </summary>
		public ThreadState State
		{
			get { return m_state; }
		}

		#endregion

		/// <summary>
		/// Returns a <see cref="System.Threading.Thread"/> equivalent for the ThreadEx instance
		/// </summary>
		/// <param name="threadEx">The ThreadEx to convert</param>
		/// <returns>A <see cref="System.Threading.Thread"/></returns>
		public static implicit operator Thread (ThreadEx threadEx)
		{
			return threadEx.m_thread;
		}

		/// <summary>
		/// Initializes a new instance of the Thread class.
		/// </summary>
		/// <param name="start">A <see cref="System.Threading.ThreadStart"/> delegate that references the methods to be invoked when this thread begins executing.</param>
		public ThreadEx(System.Threading.ThreadStart start)
		{
			if(start == null)
				throw new ArgumentNullException();

			m_terminationEvent = OpenNETCF.Win32.Core.CreateEvent(true, false, OpenNETCF.GuidEx.NewGuid().ToString());

			m_start = start;
			m_thread = new Thread(new ThreadStart(ShimProc));
			m_name = null;
			m_state = ThreadState.Unstarted;
		}

		/// <summary>
		/// Causes the operating system to change the state of the current instance to <see cref="ThreadState.Running"/>.
		/// </summary>
		public void Start()
		{
			lock(this)
			{
				m_thread.Start();
				m_handle = GetThreadHandle(m_thread);
				m_state = ThreadState.Running;
			}
		}

		/// <summary>
		/// Either suspends the thread, or if the thread is already suspended, has no effect.
		/// </summary>
		public void Suspend()
		{
			if((m_state == ThreadState.Unstarted) || (m_state == ThreadState.Stopped))
				throw new ThreadStateException();

			m_state = ThreadState.SuspendRequested;

			lock(this)
			{
				SuspendThread(m_handle);
			}

			m_state = ThreadState.Suspended;
		}

		/// <summary>
		/// Resumes a thread that has been suspended.
		/// </summary>
		public void Resume()
		{
			if(m_state != ThreadState.Suspended)
				throw new ThreadStateException();

			lock(this)
			{
				ResumeThread(m_handle);
			}
			m_state = ThreadState.Running;
		}

		private static IntPtr GetThreadHandle(Thread thread)
		{
			// ah, the magic of reflection!  Thanks to Alex Feinman for helping me on this
			return ((IntPtr)typeof(Thread).GetField("m_ThreadId", BindingFlags.NonPublic|BindingFlags.Instance).GetValue(thread));
		}

		/// <summary>
		/// Terminates the running thread.  This method will <b>always</b> throw a <see cref="BestPracticeViolationException"/>
		/// </summary>
		public void Abort()
		{	
			lock(this)
			{
				// terminate the thread
				TerminateThread(m_handle, 0);

				// set the termination event to notify Joins
				Core.SetEvent(m_terminationEvent);

				// set the state
				m_state = ThreadState.Stopped;

				// yield
				Thread.Sleep(0);
			}

			throw new BestPracticeViolationException("Aborting a thread is almost always bad practice.  Consider rearchitecting the calling code.");
		}

		/// <summary>
		/// Blocks the calling thread until a thread terminates or the specified time elapses.
		/// </summary>
		/// <returns><b>true</b> if the thread has terminated;</returns>
		public bool Join()
		{
			return Join(Core.INFINITE);
		}

		/// <summary>
		/// Blocks the calling thread until a thread terminates or the specified time elapses.
		/// </summary>
		/// <param name="millisecondsTimeout">The number of milliseconds to wait for the thread to terminate.</param>
		/// <returns><b>true</b> if the thread has terminated; <b>false</b> if the thread has not terminated after the amount of time specified by the <i>millisecondsTimeout</i> parameter has elapsed.</returns>
		public bool Join(int millisecondsTimeout)
		{
			return Join((uint)millisecondsTimeout);
		}

		/// <summary>
		/// Blocks the calling thread until a thread terminates or the specified time elapses.
		/// </summary>
		/// <param name="timeout"></param>
		/// <returns><b>true</b> if the thread has terminated; <b>false</b> if the thread has not terminated after the amount of time specified by the <i>timeout</i> parameter has elapsed.</returns>
		public bool Join(TimeSpan timeout)
		{
			return Join(Convert.ToInt32(timeout.TotalMilliseconds));
		}

		private bool Join(uint timeout)
		{
			// mimic full framework functionality
			if((m_state == ThreadState.Unstarted) || (m_state == ThreadState.Stopped))
				throw new ThreadStateException();

			lock(this)
			{
				m_state = ThreadState.WaitSleepJoin;

				if(Core.WaitForSingleObject(m_terminationEvent, timeout) == Core.Wait.Object)
				{
					m_state = ThreadState.Stopped;
					return true;
				}

				return false;
			}
		}

		private void ShimProc()
		{
			// call into actual thread proc
			m_start();

			// set the termination event to notify Joins
			Core.SetEvent(m_terminationEvent);

			// set the thread to stopped
			m_state = ThreadState.Stopped;

			// yield
			Thread.Sleep(0);
		}

		[DllImport("coredll.dll", EntryPoint="TerminateThread", SetLastError = true)]
		private static extern bool TerminateThread(IntPtr hThread, uint dwExitCode);

		[DllImport("coredll.dll", EntryPoint="SuspendThread", SetLastError = true)]
		private static extern uint SuspendThread(IntPtr hThread);

		[DllImport("coredll.dll", EntryPoint="ResumeThread", SetLastError = true)]
		private static extern uint ResumeThread(IntPtr hThread);
	}

	/// <summary>
	/// Specifies the execution states of a <see cref="ThreadEx"/>.
	/// </summary>
	public enum ThreadState : int
	{
		/// <summary>
		/// Thread is unstarted
		/// </summary>
		Unstarted,
		/// <summary>
		/// Thread is running
		/// </summary>
		Running,
		/// <summary>
		/// Thread is waiting in a Join
		/// </summary>
		WaitSleepJoin,
		/// <summary>
		/// Suspend has been called but not acted upon
		/// </summary>
		SuspendRequested,
		/// <summary>
		/// Thread is suspended
		/// </summary>
		Suspended,
		/// <summary>
		/// Thread has either terminated or been Aborted
		/// </summary>
		Stopped
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -