C#下面能產生每秒65535個我無重復ID,但是毫無規則可言。
1 private static int id = 0; 2 3 private static int serverID = 1; 4 5 /// <summary> 6 /// 下面這段代碼在一秒內,只能生產 65535 個操過了生產是會重復ID 的 7 /// </summary> 8 /// <returns></returns> 9 public static long getId() 10 { 11 lock (typeof(string)) 12 { 13 id += 1; 14 return (serverID & 0xFFFF) << 48 | (DateTime.Now.CurrentTimeMillis() / 1000L & 0xFFFFFFFF) << 16 | id & 0xFFFF; 15 } 16 }
======================
C#程序單例模式。某些非web程序,需要驗證單例模式,只能開啟一個客戶端。
目前我曉得的方式調用win32API,
static Mutex mutex; /// <summary> /// 單例模式 /// </summary> /// <param name="strMutex">系統互斥名,任意設置標識就行</param> static public void Singleton(string strMutex = "SzExtensions") { bool createdNew; //系統能夠識別有名稱的互斥,因此可以使用它禁止應用程序啟動兩次 //第二個參數可以設置為產品的名稱:Application.ProductName //每次啟動應用程序,都會驗證名稱為SingletonWinAppMutex的互斥是否存在 mutex = new Mutex(true, strMutex, out createdNew); //如果已運行,則在前端顯示 //createdNew == false,說明程序已運行 if (!createdNew) { Process instance = GetExistProcess(); //如果程序已經啟動,設置為前端顯示 if (instance != null) { SetForegroud(instance); } //退出當前程序 System.Environment.Exit(0); } } /// <summary> /// 查看程序是否已經運行 /// </summary> /// <returns></returns> static Process GetExistProcess() { Process currentProcess = Process.GetCurrentProcess(); foreach (Process process in Process.GetProcessesByName(currentProcess.ProcessName)) { if ((process.Id != currentProcess.Id) && (Assembly.GetExecutingAssembly().Location == currentProcess.MainModule.FileName)) { return process; } } return null; } /// <summary> /// 使程序前端顯示 /// </summary> /// <param name="instance"></param> static void SetForegroud(Process instance) { IntPtr mainFormHandle = instance.MainWindowHandle; if (mainFormHandle != IntPtr.Zero) { ShowWindowAsync(mainFormHandle, 1); SetForegroundWindow(mainFormHandle); } }
程序啟動的時候創建一個系統互斥量,設置一個互斥量又好名稱就可以。防止程序第二次啟動。
在開發WPF或者WF程序的時候,為了方便測試需要打印一些臨時數據。但是打印是一個非常麻煩的事情,不像控制台程序那樣可以直接輸出。非常便利。那麼我們WPF或者WF程序可不可以以打開控制台輸出呢?
網上查詢了一下可以調用win32API實現打開控制台。其實也就是打開程序的一個輸入和輸出流而已。
[DllImport("User32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] public static extern IntPtr GetForegroundWindow(); [MethodImpl(MethodImplOptions.ForwardRef), DllImport("user32.dll")] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [MethodImpl(MethodImplOptions.ForwardRef), DllImport("kernel32.dll")] private static extern bool FreeConsole(); [MethodImpl(MethodImplOptions.ForwardRef), DllImport("Kernel32.dll")] private static extern bool AllocConsole(); [MethodImpl(MethodImplOptions.ForwardRef), DllImport("user32.dll")] private static extern IntPtr GetSystemMenu(IntPtr hWnd, IntPtr bRevert); [MethodImpl(MethodImplOptions.ForwardRef), DllImport("user32.dll")] private static extern bool ShowWindowAsync(IntPtr hwind, int cmdShow); [MethodImpl(MethodImplOptions.ForwardRef), DllImport("user32.dll")] private static extern IntPtr RemoveMenu(IntPtr hMenu, uint uPosition, uint uFlags); private static string ConsoleTitle = string.Empty; private static bool flag_console = false; private static System.Timers.Timer Console_Timer; /// <summary> /// 關閉/隱藏控制台 窗體 /// </summary> static public void Console_Hide() { if (Console_Timer != null) { Console_Timer.Stop(); } flag_console = false; FreeConsole(); } /// <summary> /// 顯示控制台,一旦顯示就不會再調用第二次 /// </summary> /// <param name="title">顯示的標題</param> /// <param name="withCloseBox">是否移除關閉按鈕,默認值:false 顯示</param> /// <param name="isShowThreadCount">在控制台顯示線程數量,默認值:true 顯示</param> static public void Console_Show(string title, [MarshalAs(UnmanagedType.U1)] bool withCloseBox, [MarshalAs(UnmanagedType.U1)] bool isShowThreadCount) { //檢測flag_console,防止調用兩次 //直接用win32api //順便移除窗口 if (!flag_console) { flag_console = true; AllocConsole(); Console.Title = title; if (withCloseBox) { RemoveMenu(); } if (isShowThreadCount) { ShowThreadCount(title); } else { Console.Title = title; } } } /// <summary> /// 移除關閉按鈕 /// </summary> static void RemoveMenu() { IntPtr mainFormHandle = GetForegroundWindow(); RemoveMenu(GetSystemMenu(mainFormHandle, IntPtr.Zero), 0xf060, 0); } /// <summary> /// 在控制台title顯示線程量 /// </summary> /// <param name="title"></param> public static void ShowThreadCount(string title) { ConsoleTitle = title; Console_Timer = new System.Timers.Timer(200); Console_Timer.Elapsed += (obj, e) => { int thrads = Process.GetCurrentProcess().Threads.Count; int runthreads = 0; foreach (ProcessThread item in Process.GetCurrentProcess().Threads) if (item.ThreadState == System.Diagnostics.ThreadState.Running) runthreads++; long mem = System.Environment.WorkingSet / 1024 / 1024; Console.Title = string.Format("{0} -> 當前內存占用 -> {3} MB -> 當前線程量 -> {1} -> 當前活動線程: -> {2}", ConsoleTitle, thrads, runthreads, mem); }; Console_Timer.Start(); }
在此加入了,控制台的打開和關閉功能性輔助代碼。並且加入了控制台標題查看內存和線程使用情況。
還有一個非常方便的方式打開WPF和WF控制台輸入輸出流的方式。只能臨時使用的辦法。那就是右鍵項目屬性,選擇更改項目類型,把windows應用程序改為控制台程序。可以實現,WPF和WF程序打開控制輸入輸出流。
日志輔助========================================
日志輔助線程
1 /** 2 * 3 * @author 失足程序員 4 * @Blog http://www.cnblogs.com/ty408/ 5 * @mail [email protected] 6 * @phone 13882122019 7 * 8 */ 9 namespace Sz 10 { 11 /// <summary> 12 /// 線程模型 13 /// </summary> 14 internal class ThreadModel 15 { 16 public bool IsStop = false; 17 /// <summary> 18 /// ID 19 /// </summary> 20 public int ID; 21 22 static int StaticID = 0; 23 24 public ThreadModel(string name) 25 { 26 lock (typeof(ThreadModel)) 27 { 28 StaticID++; 29 } 30 ID = StaticID; 31 System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(Run)); 32 thread.Name = name; 33 thread.IsBackground = true; 34 thread.Start(); 35 } 36 37 /// <summary> 38 /// 任務隊列 39 /// </summary> 40 protected System.Collections.Concurrent.ConcurrentQueue<TaskBase> taskQueue = new System.Collections.Concurrent.ConcurrentQueue<TaskBase>(); 41 42 /// <summary> 43 /// 加入任務 44 /// </summary> 45 /// <param name="t"></param> 46 public virtual void AddTask(TaskBase t) 47 { 48 taskQueue.Enqueue(t); 49 ///防止線程正在阻塞時添加進入了新任務 50 are.Set(); 51 } 52 53 //通知一個或多個正在等待的線程已發生事件 54 protected ManualResetEvent are = new ManualResetEvent(false); 55 56 protected virtual void Run() 57 { 58 while (true) 59 { 60 while (!taskQueue.IsEmpty) 61 { 62 TaskBase t = null; 63 if (!taskQueue.IsEmpty && taskQueue.TryDequeue(out t)) 64 { 65 try 66 { 67 t.TaskRun();//執行任務 68 t = null; 69 } 70 catch (Exception ex) 71 { 72 Logger.Error("Thread:<" + Thread.CurrentThread.Name + "> TaskRun <" + t.Name + ">", ex); 73 } 74 } 75 } 76 are.Reset(); 77 ///隊列為空等待200毫秒繼續 78 are.WaitOne(200); 79 } 80 } 81 } 82 }
日志輔助任務執行器
1 /** 2 * 3 * @author 失足程序員 4 * @Blog http://www.cnblogs.com/ty408/ 5 * @mail [email protected] 6 * @phone 13882122019 7 * 8 */ 9 namespace Sz 10 { 11 internal abstract class TaskBase 12 { 13 14 public string Name { get; private set; } 15 16 public TaskBase(string name) 17 { 18 this.Name = name; 19 TempAttribute = new ObjectAttribute(); 20 } 21 public ObjectAttribute TempAttribute { get; set; } 22 23 public abstract void TaskRun(); 24 } 25 }
1 /** 2 * 3 * @author 失足程序員 4 * @Blog http://www.cnblogs.com/ty408/ 5 * @mail [email protected] 6 * @phone 13882122019 7 * 8 */ 9 namespace Sz 10 { 11 /// <summary> 12 /// 日志輔助 13 /// </summary> 14 public class Logger 15 { 16 static ThreadModel logConsoleThread = new ThreadModel("Console Log Thread"); 17 static ThreadModel logFileThread = new ThreadModel("File Log Thread"); 18 static string loginfoPath = "log/info/"; 19 static string logErrorPath = "log/error/"; 20 21 static Logger() 22 { 23 if (!Directory.Exists(loginfoPath)) { Directory.CreateDirectory(loginfoPath); } 24 if (!Directory.Exists(logErrorPath)) { Directory.CreateDirectory(logErrorPath); } 25 } 26 27 #region 日子寫入文件輔助任務 class LogTaskFile : TaskBase 28 /// <summary> 29 /// 日子寫入文件輔助任務 30 /// </summary> 31 class LogTaskFile : TaskBase 32 { 33 string msg, mathed; 34 Exception exce; 35 int lineID; 36 public LogTaskFile(int lineID, string mathed, string msg, Exception exce) 37 : base("File Log Task") 38 { 39 this.mathed = mathed; 40 this.lineID = lineID; 41 this.msg = msg; 42 this.exce = exce; 43 } 44 45 public LogTaskFile(string msg, Exception exce) 46 : base("File Log Task") 47 { 48 this.msg = msg; 49 this.exce = exce; 50 } 51 52 public override void TaskRun() 53 { 54 string loginfo = "[" + DateTime.Now.NowString() + mathed.PadRight(5) + "] " + msg; 55 DateTime dnow = DateTime.Now; 56 string logPath = string.Format("{0}info_{1}{2}{3}.log", loginfoPath, dnow.Year, dnow.Month, dnow.Day); 57 if (!mathed.Equals("Error")) 58 { 59 System.IO.File.AppendAllText(logPath, loginfo, UTF8Encoding.Default); 60 System.IO.File.AppendAllText(logPath, "\r\n", UTF8Encoding.Default); 61 } 62 if (exce != null) 63 { 64 logPath = string.Format("{0}error_{1}{2}{3}.log", logErrorPath, dnow.Year, dnow.Month, dnow.Day); 65 StringBuilder sb = new StringBuilder(); 66 sb.AppendLine(loginfo); 67 sb.AppendLine("----------------------Exception--------------------------"); 68 sb.AppendLine(exce.Message); 69 sb.AppendLine(exce.StackTrace); 70 sb.AppendLine("----------------------Exception--------------------------"); 71 System.IO.File.AppendAllText(logPath, sb.ToString(), UTF8Encoding.Default); 72 System.IO.File.AppendAllText(logPath, "\r\n", UTF8Encoding.Default); 73 } 74 } 75 } 76 #endregion 77 78 #region 日志寫入控制台輸出 class LogTaskConsole : TaskBase 79 /// <summary> 80 /// 日志寫入控制台輸出 81 /// </summary> 82 class LogTaskConsole : TaskBase 83 { 84 string msg, mathed; 85 Exception exce; 86 int lineID; 87 public LogTaskConsole(int lineID, string mathed, string msg, Exception exce) 88 : base("Console Log Task") 89 { 90 this.mathed = mathed; 91 this.lineID = lineID; 92 this.msg = msg; 93 this.exce = exce; 94 } 95 96 public LogTaskConsole(string msg, Exception exce) 97 : base("Console Log Task") 98 { 99 this.msg = msg; 100 this.exce = exce; 101 } 102 103 public override void TaskRun() 104 { 105 string loginfo = "[" + DateTime.Now.NowString() + mathed.PadRight(5) + "] " + msg; 106 DateTime dnow = DateTime.Now; 107 Console.WriteLine(loginfo); 108 109 if (exce != null) 110 { 111 StringBuilder sb = new StringBuilder(); 112 sb.AppendLine(loginfo); 113 sb.AppendLine("----------------------Exception--------------------------"); 114 sb.AppendLine(exce.Message); 115 sb.AppendLine(exce.StackTrace); 116 sb.AppendLine("----------------------Exception--------------------------"); 117 Console.WriteLine(sb.ToString()); 118 } 119 } 120 } 121 #endregion 122 123 string name; 124 public Logger(string name) 125 { 126 this.name = name; 127 } 128 129 static public void Info(string msg) 130 { 131 AddLog(0, "Info", msg, null); 132 } 133 134 static public void Error(string msg) 135 { 136 Error(msg, null); 137 } 138 139 static public void Error(string msg, Exception exception) 140 { 141 AddLog(0, "Error", msg, exception); 142 } 143 144 static void AddLog(int lineID, string mathed, string msg, Exception exception) 145 { 146 LogTaskConsole logConsole = new LogTaskConsole(lineID, mathed, msg, exception); 147 logConsoleThread.AddTask(logConsole); 148 LogTaskFile logFile = new LogTaskFile(lineID, mathed, msg, exception); 149 logFileThread.AddTask(logFile); 150 } 151 } 152 }
自己動手實現日志記錄功能,,雖然不比log4net的功能強大,但是沒有那麼臃腫。能給滿足自我需求。