static class Program { ////// 应用程序的主入口点。 /// [STAThread] static void Main() { try { //添加事件处理程序未捕获的异常 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); //添加事件处理UI线程异常 Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); //添加事件处理非UI线程异常 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new FrmActivity()); } catch (Exception ex) { string str = ""; string strDateInfo = "出现应用程序未处理的异常:" + DateTime.Now.ToString() + "\r\n"; if (ex != null) { str = string.Format(strDateInfo + "异常类型:{0}\r\n异常消息:{1}\r\n异常信息:{2}\r\n", ex.GetType().Name, ex.Message, ex.StackTrace); } else { str = string.Format("应用程序线程错误:{0}", ex); } //写日志 WriteLog.WriteErrLog(str); MessageBox.Show("发生致命错误,请及时联系作者!", "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } /// ///这就是我们要在发生未处理异常时处理的方法,做法很多,可以是把出错详细信息记录到文本、数据库,发送出错邮件到作者信箱或出错后重新初始化等等 /// /// /// static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) { string str = ""; string strDateInfo = "出现应用程序未处理的异常:" + DateTime.Now.ToString() + "\r\n"; Exception error = e.Exception as Exception; if (error != null) { str = string.Format(strDateInfo + "异常类型:{0}\r\n异常消息:{1}\r\n异常信息:{2}\r\n", error.GetType().Name, error.Message, error.StackTrace); } else { str = string.Format("应用程序线程错误:{0}", e); } //写日志 WriteLog.WriteErrLog(str); MessageBox.Show("发生致命错误,请及时联系作者!", "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } /// /// ' 处理UI异常 /// /// /// static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { string str = ""; Exception error = e.ExceptionObject as Exception; string strDateInfo = "出现应用程序未处理的异常:" + DateTime.Now.ToString() + "\r\n"; if (error != null) { str = string.Format(strDateInfo + "Application UnhandledException:{0};\n\r堆栈信息:{1}", error.Message, error.StackTrace); } else { str = string.Format("Application UnhandledError:{0}", e); } //写日志 WriteLog.WriteErrLog(str); MessageBox.Show("发生致命错误,请停止当前操作并及时联系作者!", "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
The above code can capture exception that are generated by new Thread(()=>{throw new Exception();}).Start();
but cannot capture Task exception; For tasks, refer to below and see relevant;
Ps:
Exception handling in Task parallel library:
while(!task1.IsCompleted){}// Or Task.Wait(); and catch the exception in UI thread;
if(task.status==TaskStatus.falted){
foreach(var e in task1.Exception.InnerException){
//Log the exception
}
}
async button event handler method triggers task exception to UI thread;
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/exception-handling-task-parallel-library
Make use of SynchronizationContext in synchronous methods to operate UI thread:
var ctx = SynchronizationContext.Current; new Thread(() => { Thread.Sleep(3000); ctx.Post(d => { this.panel2.Controls.Add(new Button { Text = "aa", Width = 15, Height = 15 }); }, null); }).Start();
How to debug a parallel application:
https://docs.microsoft.com/en-us/visualstudio/debugger/walkthrough-debugging-a-parallel-application?view=vs-2019#c-sample
Flexible use of empty condition block {} to isolate code is a good way to avoid hard naming case; like { a=0; return 1;} {a=0; return 2;}, this code is valid but name a can be used in both scopes.
[InvocationList]https://blog.csdn.net/zxkid/article/details/1444396
public static Delegate[] GetComponentEventDelegate(Component component, string EventName, string EventHandlerTypeName) { Type componentType = component.GetType(); PropertyInfo eventsPropertyInfo = componentType.GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic); EventHandlerList eventHanlderList = eventsPropertyInfo.GetValue(component, null) as EventHandlerList; FieldInfo HeadFieldInfo = eventHanlderList.GetType().GetField("head", BindingFlags.Instance | BindingFlags.NonPublic); object HeadObject = HeadFieldInfo.GetValue(eventHanlderList); do { FieldInfo[] fieldInfoList = componentType.GetFields(BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fieldInfoList) { object fieldValue = fieldInfo.GetValue(component); if (fieldValue != null) { Type fieldType = fieldValue.GetType(); if (fieldType.Name == EventHandlerTypeName && (fieldValue as Delegate) != null) { return (fieldValue as Delegate).GetInvocationList(); } else if (fieldType.Name == typeof(Object).Name) { if (fieldInfo.Name.IndexOf(EventName, StringComparison.OrdinalIgnoreCase) > -1) { if (HeadObject != null) { Delegate delegateObject = eventHanlderList[fieldValue]; if (delegateObject != null) return delegateObject.GetInvocationList(); } } } } } componentType = componentType.BaseType; } while (componentType != null); if (HeadObject != null) { object ListEntry = HeadObject; Type ListEntryType = ListEntry.GetType(); FieldInfo handlerFieldInfo = ListEntryType.GetField("handler", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo keyFieldInfo = ListEntryType.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo nextFieldInfo = ListEntryType.GetField("next", BindingFlags.Instance | BindingFlags.NonPublic); while (ListEntry != null) { Delegate handler = handlerFieldInfo.GetValue(ListEntry) as Delegate; object key = keyFieldInfo.GetValue(ListEntry); ListEntry = nextFieldInfo.GetValue(ListEntry); if (handler != null && handler.GetType().Name == EventHandlerTypeName) return handler.GetInvocationList(); } } return null; }
[Editor](https://github.com/jacobslusser/ScintillaNET)
Threadpool play method thought of by experiment by me?:
public volatile static int flag = 0; public static JObject config = new JObject(); static ManualResetEvent _event = new ManualResetEvent(false); ////// The main entry point for the application. /// [STAThread] static void Main() { List threads = new List (); Action action = () => { }; Thread th = new Thread(() => { while (flag != 1) { action(); //Monitor.Enter(config); //Thread.CurrentThread.Suspend(); _event.WaitOne(); } }) { IsBackground = true }; th.Start(); threads.Add(th); Thread.Sleep(500); var state = threads[0].ThreadState; var isRunning = threads[0].IsAlive; //start the thread again action = () => { }; _event.Reset(); _event.Set(); //threads[0].Resume(); //Monitor.Exit(config); Semaphore s = new Semaphore(2, 4);
Semaphore reprinted:
Semaphore:可理解为允许线程执行信号的池子,池子中放入多少个信号就允许多少线程同时执行。 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 private static void MultiThreadSynergicWithSemaphore() { //0表示创建Semaphore时,拥有可用信号量数值 //1表示Semaphore中,最多容纳信号量数值 Semaphore semaphore = new Semaphore(0, 1); Thread thread1 = new Thread(() => { //线程首先WaitOne等待一个可用的信号量 semaphore.WaitOne(); //在得到信号量后,执行下面代码内容 Console.WriteLine("thread1 work"); Thread.Sleep(5000); //线程执行完毕,将获得信号量释放(还给semaphore) semaphore.Release(); }); Thread thread2 = new Thread(() => { semaphore.WaitOne(); Console.WriteLine("thread2 work"); Thread.Sleep(5000); semaphore.Release(); }); thread2.Start(); thread1.Start(); //因在创建Semaphore时拥有的信号量为0 //semaphore.Release(1) 为加入1个信号量到semaphore中 semaphore.Release(1); } 说明: 1、如果semaphore.Release(n),n>semaphore最大容纳信号量,将出异常。 2、当semaphore拥有的信号量为1时,Semaphore相当于Mutex 3、当semaphore拥有的信号量>1时,信号量的数量即可供多个线程同时获取的个数,此时可认为获取到信号量的线程将同时执行(实际情况可能与CPU核心数、CPU同时支出线程数有关)
Multidownload reprinted:
public class MultiDownload { #region 变量 private int _threadNum; //线程数量 private long _fileSize; //文件大小 private string _fileUrl; //文件地址 private string _fileName; //文件名 private string _savePath; //保存路径 private short _threadCompleteNum; //线程完成数量 private bool _isComplete; //是否完成 private volatile int _downloadSize; //当前下载大小(实时的) private Thread[] _thread; //线程数组 private List<string> _tempFiles = new List<string>(); private object locker = new object(); #endregion #region 属性 ////// 文件名 /// public string FileName { get { return _fileName; } set { _fileName = value; } } /// /// 文件大小 /// public long FileSize { get { return _fileSize; } } /// /// 当前下载大小(实时的) /// public int DownloadSize { get { return _downloadSize; } } /// /// 是否完成 /// public bool IsComplete { get { return _isComplete; } } /// /// 线程数量 /// public int ThreadNum { get { return _threadNum; } } /// /// 保存路径 /// public string SavePath { get { return _savePath; } set { _savePath = value; } } #endregion /// /// 构造函数 /// /// 线程数量 /// 文件Url路径 /// 本地保存路径 public MultiDownload(int threahNum, string fileUrl, string savePath) { this._threadNum = threahNum; this._thread = new Thread[threahNum]; this._fileUrl = fileUrl; this._savePath = savePath; } public void Start() { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_fileUrl); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); _fileSize = response.ContentLength; int singelNum = (int)(_fileSize / _threadNum); //平均分配 int remainder = (int)(_fileSize % _threadNum); //获取剩余的 request.Abort(); response.Close(); for (int i = 0; i < _threadNum; i++) { List<int> range = new List<int>(); range.Add(i * singelNum); if (remainder != 0 && (_threadNum - 1) == i) //剩余的交给最后一个线程 range.Add(i * singelNum + singelNum + remainder - 1); else range.Add(i * singelNum + singelNum - 1); //下载指定位置的数据 int[] ran = new int[] { range[0], range[1] }; _thread[i] = new Thread(new ParameterizedThreadStart(Download)); _thread[i].Name = System.IO.Path.GetFileNameWithoutExtension(_fileUrl) + "_{0}".Replace("{0}", Convert.ToString(i + 1)); _thread[i].Start(ran); } //MessageBox.Show("下载完成!"); } private void Download(object obj) { Stream httpFileStream = null, localFileStram = null; try { int[] ran = obj as int[]; string tmpFileBlock = System.IO.Path.GetTempPath() + Thread.CurrentThread.Name + ".tmp"; _tempFiles.Add(tmpFileBlock); HttpWebRequest httprequest = (HttpWebRequest)WebRequest.Create(_fileUrl); httprequest.AddRange(ran[0], ran[1]); HttpWebResponse httpresponse = (HttpWebResponse)httprequest.GetResponse(); httpFileStream = httpresponse.GetResponseStream(); localFileStram = new FileStream(tmpFileBlock, FileMode.Create); byte[] by = new byte[5000]; int getByteSize = httpFileStream.Read(by, 0, (int)by.Length); //Read方法将返回读入by变量中的总字节数 while (getByteSize > 0) { Thread.Sleep(20); lock (locker) _downloadSize += getByteSize; localFileStram.Write(by, 0, getByteSize); getByteSize = httpFileStream.Read(by, 0, (int)by.Length); } lock (locker) _threadCompleteNum++; } catch (Exception ex) { throw new Exception(ex.Message.ToString()); } finally { if (httpFileStream != null) httpFileStream.Dispose(); if (localFileStram != null) localFileStram.Dispose(); } if (_threadCompleteNum == _threadNum) { Complete(); _isComplete = true; } } /// /// 下载完成后合并文件块 /// private void Complete() { Stream mergeFile = null; BinaryWriter AddWriter = null; try { using (mergeFile = new FileStream(@_savePath, FileMode.Create)) //根据实际情况调整FileMode { AddWriter = new BinaryWriter(mergeFile); foreach (string file in _tempFiles) { using (FileStream fs = new FileStream(file, FileMode.Open)) { BinaryReader TempReader = new BinaryReader(fs); AddWriter.Write(TempReader.ReadBytes((int)fs.Length)); TempReader.Close(); } File.Delete(file); } } MyMessageBox.Show("下载完成!"); } catch (Exception ex) { throw new Exception(ex.Message); } finally { if (AddWriter != null) { AddWriter.Close(); AddWriter.Dispose(); } if (mergeFile != null) { mergeFile.Close(); mergeFile.Dispose(); } } } }
Mutex reprinted:
#region 只能运行一个程序 bool flag = false; Mutex mutex = new Mutex(true, "Test", out flag); //第一个参数:true--给调用线程赋予互斥体的初始所属权 //第一个参数:互斥体的名称 //第三个参数:返回值,如果调用线程已被授予互斥体的初始所属权,则返回true if (!flag) { MessageBox.Show("程序已运行!", "确定", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); Environment.Exit(1);//退出程序 } #endregion }
Volatile reprinted:
恐怕比较一下volatile和synchronized的不同是最容易解释清楚的。volatile是变量修饰符,而synchronized则作用于一段代码或方法;看如下三句get代码: int i1; int geti1() {return i1;} volatile int i2; int geti2() {return i2;} int i3; synchronized int geti3() {return i3;} geti1()得到存储在当前线程中i1的数值。多个线程有多个i1变量拷贝,而且这些i1之间可以互不相同。换句话说,另一个线程可能已经改变了它线程内的i1值,而这个值可以和当前线程中的i1值不相同。事实上,Java有个思想叫“主”内存区域,这里存放了变量目前的“准确值”。每个线程可以有它自己的变量拷贝,而这个变量拷贝值可以和“主”内存区域里存放的不同。因此实际上存在一种可能:“主”内存区域里的i1值是1,线程1里的i1值是2,线程2里的i1值是3——这在线程1和线程2都改变了它们各自的i1值,而且这个改变还没来得及传递给“主”内存区域或其他线程时就会发生。 而geti2()得到的是“主”内存区域的i2数值。用volatile修饰后的变量不允许有不同于“主”内存区域的变量拷贝。换句话说,一个变量经volatile修饰后在所有线程中必须是同步的;任何线程中改变了它的值,所有其他线程立即获取到了相同的值。理所当然的,volatile修饰的变量存取时比一般变量消耗的资源要多一点,因为线程有它自己的变量拷贝更为高效。 既然volatile关键字已经实现了线程间数据同步,又要synchronized干什么呢?呵呵,它们之间有两点不同。首先,synchronized获得并释放监视器——如果两个线程使用了同一个对象锁,监视器能强制保证代码块同时只被一个线程所执行——这是众所周知的事实。但是,synchronized也同步内存:事实上,synchronized在“主”内存区域同步整个线程的内存。因此,执行geti3()方法做了如下几步: 1. 线程请求获得监视this对象的对象锁(假设未被锁,否则线程等待直到锁释放) 2. 线程内存的数据被消除,从“主”内存区域中读入(Java虚拟机能优化此步。。。[后面的不知道怎么表达,汗]) 3. 代码块被执行 4. 对于变量的任何改变现在可以安全地写到“主”内存区域中(不过geti3()方法不会改变变量值) 5. 线程释放监视this对象的对象锁 因此volatile只是在线程内存和“主”内存间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。显然synchronized要比volatile消耗更多资源。
Exercise:
private class ThreadPool { //to be performant private int maxSize = 5; private Listthreads = new List (); private volatile Action _runable; private void StartNew(Action action) { this._runable = action; if (threads.Count < maxSize) { var t = new Thread(() => { while (true) { _runable(); Thread.CurrentThread.Suspend(); } }); t.Start(); threads.Add(t); } else { //exceed equal maxSize var t = threads.First(a => a.IsAlive && a.ThreadState != System.Threading.ThreadState.Running); t.Resume(); } } } private class ConnectionPool : IDisposable { private List pool = new List (); private int maxSize = 5; private DbConnection GetOpenConnection() { if (pool.Count < maxSize) { var conn = new SqlConnection(); pool.Add(conn); return conn; } else { //==maxSize return pool.First(c => c.State != System.Data.ConnectionState.Open); } } private bool _disposed = false; protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { pool.ForEach(c => c.Dispose()); } pool.Clear(); _disposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } ~ConnectionPool() { Dispose(false); } } public class Singleton where T : new() { private Singleton() { } public static T Instance = new T(); } public class Cache : ConcurrentDictionary<string, object> { }
GetGenericTypeDefinition
Gene<int> asd = new Gene<int>(); var aa1 = asd.GetType().GetGenericTypeDefinition(); var asd1 = aa1.Equals(typeof(Gene<>));
Practice:
using FontAwesome.Sharp; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Dynamic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace zgraphdemo { public partial class Form2 : Form { private volatile int num = 5; private static ConcurrentDictionary<string, object> instanceCache = new ConcurrentDictionary<string, object>(); public Form2() { InitializeComponent(); } private int i = 1; private TreeView tree; private void button1_Click(object sender, EventArgs e) { this.panel1.Controls.Clear(); var btn1 = this.Owner.Controls.Find("button1", true).First() as Button; btn1.Text = "returned from dialog"; var tp = typeof(Case1); var ctl = Activator.CreateInstance(tp) as UserControl; (ctl.Controls.Find("textbox1", false).First() as TextBox).Text = (i++).ToString(); ctl.Dock = DockStyle.Fill; this.pnCase.Controls.Clear(); this.pnCase.Controls.Add(ctl); tree = new TreeView(); tree.ImageList = new ImageList(); tree.ImageList.Images.Add("id", IconChar.IdCard.ToBitmap(32, Color.DeepPink)); tree.ImageList.Images.Add("state", IconChar.Box.ToBitmap(32, Color.Black)); tree.CheckBoxes = true; tree.Dock = DockStyle.Fill; tree.Nodes.Add(new TreeNode { Text = "ancestor", Tag = new { text = "ancestor", id = 0, pid = 0 } }); //tree.Nodes[0].Nodes.Add("child"); //tree.Nodes[0].Nodes[0].Nodes.Add("grandchild"); this.panel1.Controls.Add(tree); //this.Close(); if (tree != null) { tree.AfterSelect += Tree_AfterSelect; tree.AfterCheck += Tree_AfterCheck; } } class Point { public int x; public int y; } private void button2_Click(object sender, EventArgs e) { Program.flag = 1; if (tree == null) return; //tree.Nodes[0].ImageKey = "state"; //tree.Nodes[0].Tag = 0; var nodes = new List<dynamic>() { new {text="1",id=1,pid=0 }, new {text="12",id=2,pid=1 }, new {text="13",id=3,pid=1 }, new {text="2",id=4,pid=0 }, new {text="12",id=5,pid=4 }, new {text="13",id=6,pid=4 }, }; addNode(tree.Nodes[0], nodes); tree.Refresh(); var x = new Point(); unsafe { int i = 5; int* p = &i; fixed (int* p1 = &x.x) { *p1 = 22; int p2 = *p1 * 52; int[][][][][][] sdfsdf = null; } } } private void GatherNodes(TreeNode jiaobaba, Listnodes) { if (jiaobaba.Nodes.Count > 0) { nodes.AddRange(jiaobaba.Nodes.Cast ()); foreach (TreeNode item in jiaobaba.Nodes) { GatherNodes(item, nodes); } } } private void Tree_AfterCheck(object sender, TreeViewEventArgs e) { var nodes = tree.Nodes.Cast (); var ns = new List (); GatherNodes(tree.Nodes[0], ns); MessageBox.Show(ns.Count().ToString()); } private void Tree_AfterSelect(object sender, TreeViewEventArgs e) { if (!instanceCache.ContainsKey(e.Node.Text)) { instanceCache.TryAdd($"select_{e.Node.Text}", new object()); } var instance = instanceCache[$"select_{e.Node.Text}"]; instance.ToString(); MessageBox.Show(tree.Nodes.Cast ().First().Text); } private void addNode(TreeNode node, List<dynamic> nodes) { var children = nodes.Where(c => c.pid == (int)((node.Tag as dynamic).id)).ToArray(); if (children.Length > 0) { var childrenN = children.Select(c => new TreeNode { Text = c.text, Tag = c }).ToArray(); node.Nodes.AddRange(childrenN); foreach (var item in childrenN) { addNode(item, nodes); } } } } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using ZedGraph; using FontAwesome.Sharp; using System.Runtime.InteropServices; namespace zgraphdemo { public partial class Form1 : Form { private int progressCounter = 1; [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = CharSet.Auto)] extern static bool DestroyIcon(IntPtr handle); public Form1() { InitializeComponent(); //this = new FontAwesome.Sharp.Icon(IconChar.Folder); this.pictureBox2.Image= IconChar.BatteryEmpty.ToBitmap(32, Color.Blue); this.button1.Image = IconChar.Igloo.ToBitmap(32, Color.DeepPink); this.button2.Image = IconChar.IdCard.ToBitmap(32, Color.DeepPink); var img = IconChar.Cube.ToBitmap(32, Color.DeepPink); var hdl = img.GetHicon(); System.Drawing.Icon icon = System.Drawing.Icon.FromHandle(hdl); this.Icon = icon; //DestroyIcon(icon.Handle); var a = 0.000000; this.progressBar1.Visible = false; this.timeDraw.Tick += new EventHandler(timeDraw_Tick); InflateDataGridView(); cmbDrivetrainType.Enabled = false; var dfxType = new Dictionary<int, string>(); dfxType.Add(0, "FWD"); dfxType.Add(1, "RWD"); dfxType.Add(2, "AWD Permanente"); dfxType.Add(3, "AWD HangONRA"); dfxType.Add(4, "AWD HangONFA"); dfxType.Add(5, "Axlesplit"); this.cmbDrivetrainType.ValueMember = "Key"; this.cmbDrivetrainType.DisplayMember = "Value"; this.cmbDrivetrainType.DataSource = new BindingSource(dfxType, null); //for (int i = 0; i < 100; i++) //{ // this.toolStripProgressBar1.ProgressBar.Step = i; // this.toolStripProgressBar1.ProgressBar.PerformStep(); // if (i == 100) this.toolStripProgressBar1.ProgressBar.Step = 0; //} Interlocked.Increment(ref progressCounter); this.toolStripProgressBar1.ProgressBar.Maximum = 5; Interlocked.Decrement(ref progressCounter); button2.ForeColor = Color.Green; button1.BackColor = Color.DarkGoldenrod; this.button1.Click += button1_Click; this.button3.Click += button3_Click; Bitmap bitmap = new Bitmap(300, 300); Graphics g = Graphics.FromImage(bitmap); g.Clear(Color.Transparent); g.DrawLine(new Pen(Color.Blue), 0, 0, 100, 100); g.DrawEllipse(Pens.Blue, 0, 0, 10, 30); g.DrawString("Caloch", DefaultFont, Brushes.Black, 0, 0); g.Save(); g.Dispose(); //bitmap.MakeTransparent(Color.Red); bitmap.Save("dd.png", ImageFormat.Png); pictureBox1.Image = bitmap; } private void InflateDataGridView() { DataTable dt = new DataTable(); dt.Columns.Add("id"); dt.Columns.Add("text"); dt.Columns.Add("Delete"); var row = dt.NewRow(); row["id"] = 1; row["text"] = "text"; row["Delete"] = "Delete"; dt.Rows.Add(row); this.dataGridView1.DataSource = dt; } // 起始时间以毫秒为单位 int tickStart = 0; private void Form1_Load(object sender, EventArgs e) { //获取引用 GraphPane myPane = zedGraphControl1.GraphPane; FormatGraphPane(myPane); FormatXAxis(myPane.XAxis); FormatYAxis(myPane.YAxis); //设置标题 myPane.Title.Text = "实时曲线"; //设置X轴说明文字 myPane.XAxis.Title.Text = "时间"; //设置Y轴说明文字 myPane.YAxis.Title.Text = "温度"; //设置1200个点,假设每50毫秒更新一次,刚好检测1分钟,一旦构造后将不能更改这个值 RollingPointPairList list = new RollingPointPairList(1200); //开始,增加的线是没有数据点的(也就是list为空) //增加一条名称:Voltage,颜色Color.Bule,无符号,无数据的空线条 LineItem curve = myPane.AddCurve("温度", list, Color.Blue, SymbolType.None); myPane.AxisChangeEvent += MyPane_AxisChangeEvent; timeDraw.Interval = 1000; //设置timer控件的间隔为50毫秒 timeDraw.Enabled = true; //timer可用 timeDraw.Start(); //开始 myPane.XAxis.Scale.Min = 0; //X轴最小值0 myPane.XAxis.Scale.Max = 30; //X轴最大30 myPane.XAxis.Scale.MinorStep = 1;//X轴小步长1,也就是小间隔 myPane.XAxis.Scale.MajorStep = 5;//X轴大步长为5,也就是显示文字的大间隔 //改变轴的刻度 zedGraphControl1.AxisChange(); //保存开始时间 tickStart = Environment.TickCount; } private void MyPane_AxisChangeEvent(GraphPane pane) { pane.XAxis.Color = Color.Green; } public GraphPane FormatGraphPane(GraphPane gp) { gp.Border.IsVisible = false; gp.Title.IsVisible = false; gp.IsFontsScaled = false; gp.Margin.All = 1; gp.Legend.IsVisible = true; gp.Legend.FontSpec.Size = 11; gp.Legend.FontSpec.FontColor = Color.Black; gp.Legend.Fill = new Fill(Color.FromArgb(255, 255, 255, 255), Color.FromArgb(255, 255, 255, 255)); gp.Legend.Border.IsVisible = false; gp.Chart.Border.Color = Color.LightGray; gp.Fill = new Fill(Color.White, Color.White, 0F); gp.Chart.Fill = new Fill(Color.White, Color.White, 0); if (gp.XAxis != null) FormatXAxis(gp.XAxis); if (gp.YAxis != null) FormatYAxis(gp.YAxis); return gp; } public XAxis FormatXAxis(XAxis xAxis) { xAxis.Title.IsVisible = false; xAxis.Title.FontSpec.Size = 11; xAxis.Scale.FontSpec.Size = 11; xAxis.MajorTic.Color = Color.Gray; xAxis.MinorTic.Color = Color.LightGray; xAxis.Scale.FontSpec.FontColor = Color.Gray; xAxis.Title.FontSpec.FontColor = Color.Gray; return xAxis; } public YAxis FormatYAxis(YAxis yAxis) { yAxis.Title.IsVisible = true; yAxis.Title.FontSpec.Size = 11; yAxis.Scale.FontSpec.Size = 11; yAxis.Color = Color.LightGray; yAxis.MajorTic.Color = Color.Gray; yAxis.MinorTic.Color = Color.LightGray; yAxis.Scale.FontSpec.FontColor = Color.Gray; yAxis.Title.FontSpec.FontColor = Color.Gray; return yAxis; } private void timeDraw_Tick(object sender, EventArgs e) { //确保CurveList不为空 if (zedGraphControl1.GraphPane.CurveList.Count <= 0) { return; } //取Graph第一个曲线,也就是第一步:在GraphPane.CurveList集合中查找CurveItem LineItem curve = zedGraphControl1.GraphPane.CurveList[0] as LineItem; if (curve == null) { return; } //第二步:在CurveItem中访问PointPairList(或者其它的IPointList),根据自己的需要增加新数据或修改已存在的数据 IPointListEdit list = curve.Points as IPointListEdit; if (list == null) { return; } // 时间用秒表示 double time = (Environment.TickCount - tickStart) / 1000.0; // 3秒循环 list.Add(time, Math.Sin(2.0 * Math.PI * time / 3.0)); Console.WriteLine(time.ToString()); Scale xScale = zedGraphControl1.GraphPane.XAxis.Scale; if (time > xScale.Max - xScale.MajorStep) { xScale.Max = time + xScale.MajorStep; xScale.Min = xScale.Max - 30.0; } //第三步:调用ZedGraphControl.AxisChange()方法更新X和Y轴的范围 zedGraphControl1.AxisChange(); //第四步:调用Form.Invalidate()方法更新图表 zedGraphControl1.Invalidate(); } private void Form1_Resize(object sender, EventArgs e) { SetSize(); } private void SetSize() { // 控制始终是以10像素插入矩形从客户端的形 Rectangle formRect = this.ClientRectangle; formRect.Inflate(-10, -10); if (zedGraphControl1.Size != formRect.Size) { zedGraphControl1.Location = formRect.Location; zedGraphControl1.Size = formRect.Size; } } private void button1_Click(object sender, EventArgs e) { this.Cursor = System.Windows.Forms.Cursors.Default; DisableControls(this, true); var f2 = new Form2(); f2.ShowDialog(this); } private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex == -1) return; if (dataGridView1.Columns[e.ColumnIndex].Name == "Delete" && dataGridView1.Rows.Count > 1 && e.RowIndex != dataGridView1.Rows.Count - 1) { dataGridView1.Rows.RemoveAt(e.RowIndex); } } void DisableControls(Control ctl, bool enable) { ctl.Enabled = enable; foreach (Control sub in ctl.Controls) { DisableControls(sub, enable); } } private async void button2_Click(object sender, EventArgs e) { SynchronizationContext.Current.Post(a => { }, null); SynchronizationContext ctx = SynchronizationContext.Current; new Thread((x) => { var ctx1 = x as SynchronizationContext; ctx1.Post(a => { button3_Click(button3, new EventArgs()); DisableControls(this.panel1, false); this.Cursor = System.Windows.Forms.Cursors.WaitCursor; this.progressBar1.Visible = true; }, null); Thread.Sleep(8000); ctx1.Post(a => { var dt = dataGridView1.DataSource as DataTable; var row = dt.NewRow(); row["id"] = (int)dt.Rows.Count + 1; row["text"] = "text"; row["Delete"] = "Delete"; dt.Rows.Add(row); button3_Click(button3, new EventArgs()); DisableControls(this.panel1, true); this.Cursor = System.Windows.Forms.Cursors.Default; this.progressBar1.Visible = false; }, null); }).Start(ctx); await Task.Factory.StartNew(() => { ctx.Post(a => { button3_Click(button3, new EventArgs()); }, null); }); } private void button3_Click(object sender, EventArgs e) { //RemoveCurves("温度"); //this.zedGraphControl1.MasterPane.PaneList.Clear(); //this.zedGraphControl1.MasterPane.Add(new GraphPane()); //DataTable dt = new DataTable(); //dt.Columns.Add("id"); //dt.Columns.Add("text"); //dt.Columns.Add("Delete"); //dataGridView1.DataSource = dt; } public void RemoveCurves(params string[] names) { names.ToList().ForEach(name => { Predicatepredicate = c => { return c.Label.Text.ToUpper() == name.ToUpper(); }; var pane = this.zedGraphControl1.MasterPane.PaneList.Cast ().FirstOrDefault(p => p.CurveList.Cast ().Any(c => predicate(c))); pane?.CurveList.RemoveAt(pane.CurveList.FindIndex(predicate)); }); this.zedGraphControl1.Refresh(); System.Drawing.Rectangle rect = new Rectangle(); rect.Inflate(40, 40); } private void dataGridView1_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { int currentMouseOverRow = dataGridView1.HitTest(e.X, e.Y).RowIndex; int currentMouseOverColumn = dataGridView1.HitTest(e.X, e.Y).ColumnIndex; ContextMenu m = new ContextMenu(); var m1 = new MenuItem("Cut"); m1.Click += (a, b) => { if (currentMouseOverColumn == -1) return; MessageBox.Show(((MenuItem)a).Text + currentMouseOverRow + currentMouseOverColumn + dataGridView1.Columns[currentMouseOverColumn].Name); }; m.MenuItems.Add(m1); m.MenuItems.Add(new MenuItem("Copy")); m.MenuItems.Add(new MenuItem("Paste")); if (currentMouseOverRow >= 0) { m.MenuItems.Add(new MenuItem(string.Format("Do something to row {0}", currentMouseOverRow.ToString()))); } m.Show(dataGridView1, new Point(e.X, e.Y)); } } private void button3_Click_1(object sender, EventArgs e) { this.pictureBox2.Image = IconChar.Circle.ToBitmap(32, Color.DarkGreen); MessageBox.Show(Program.config["a"]?.ToString()); } private void button4_Click(object sender, EventArgs e) { this.pictureBox2.Image = IconChar.Circle.ToBitmap(32, Color.Red); var p = new Process(); p.StartInfo.FileName = "notepad.exe"; p.StartInfo.Arguments = "a.json"; p.Start(); } private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e) { } private void quitToolStripMenuItem_Click(object sender, EventArgs e) { this.Close(); } } }
using Newtonsoft.Json.Linq; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Data.SqlClient; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace zgraphdemo { class Gene{ } static class Program { //to synchronize value public volatile static int flag = 0; public static JObject config = new JObject(); static ManualResetEvent _event = new ManualResetEvent(false); /// /// The main entry point for the application. /// [STAThread] static void Main() { List threads = new List (); Action action = () => { }; Thread th = new Thread(() => { while (flag != 1) { action(); //Monitor.Enter(config); //Thread.CurrentThread.Suspend(); _event.WaitOne(); } }) { IsBackground = true }; th.Start(); threads.Add(th); Thread.Sleep(500); var state = threads[0].ThreadState; var isRunning = threads[0].IsAlive; //start the thread again action = () => { }; _event.Reset(); _event.Set(); //threads[0].Resume(); //Monitor.Exit(config); Semaphore s = new Semaphore(2, 4); Gene<int> asd = new Gene<int>(); var aa1 = asd.GetType().GetGenericTypeDefinition(); var asd1 = aa1.Equals(typeof(Gene<>)); var n = new int[100]; for (int i = 0; i < 100; i++) { n[i] = i; } GetByCreatia requrest1 = new GetByCreatia(); SendCommandCriteria scc = requrest1.CreateCriteria(); scc.AndUserIdEqualsTo(55); if (scc.Satisfied()) { } dynamic service = new { }; //service?.satisfy(requrest1); Mutex m1 = new Mutex(); try { config = JObject.Parse(File.ReadAllText("a.json")); new Thread(() => { FileSystemWatcher fw = new FileSystemWatcher("."); fw.Filter = "*.json"; fw.Changed += (a, aa) => { System.Threading.Thread.Sleep(500); config = JObject.Parse(File.ReadAllText("a.json")); //MessageBox.Show(config["a"]?.ToString()); //File watcher will terminate this thread after changed event is triggered if it will be disposed; }; fw.EnableRaisingEvents = true; }).Start(); } catch (Exception ex) { File.WriteAllText("log.txt", ex.Message); } var b = n as IEnumerable<int>; b.Reverse(); var c = b.Where(n1 => n1 > 10).ToList(); c.Reverse(); var d = b.Where(n1 => n1 > 10).ToArray(); var e = d.Reverse().ToArray(); TupleElementIsReadonly(); double a1 = 0; var a3 = double.TryParse(null, out a1); string[] yAxises = new string[] { "ay", "sas", "VGIF", "vxVeh_VDC", "v_FL", "v_RL", "v_FR", "v_RR", "ThrottlePos", "BlsAsw", "CtlActiveVdc" }; var y1 = yAxises.Except(new string[] { "ay" }); var y2 = yAxises.TakeWhile(v => v.StartsWith("a")).ToList(); var y = yAxises.Skip(yAxises.Length - 2).Take(2).ToArray(); var y3 = Tuple.Create(2, 3); var x = string.Join(",", yAxises.Select(a => $"\"{a}\":\"{a}\"")); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } private static void TupleElementIsReadonly() { HashSet<int> n = new HashSet<int>(); System.Collections.Generic.LinkedList<int> m1 = new LinkedList<int>(); m1.AddFirst(2); m1.AddLast(3); SortedList<int, string> n1 = new SortedList<int, string>(); m1.AddBefore(m1.First, 4); n1.Add(2, "3"); n1.Add(5, "4"); n1.Add(4, "2"); n1.Add(3, "1"); var n2 = n1.Values; Debug.Assert(n2[1] == "1"); Debug.Print("this is like sheet"); } private class GetByCreatia { public GetByCreatia() { } internal SendCommandCriteria CreateCriteria() { return new SendCommandCriteria(); } } private class SendCommandCriteria { private int userId; private Dictionary<string, Standard> standards = new Dictionary<string, Standard>(); public SendCommandCriteria() { } public bool Satisfied() { return true; } internal void AndUserIdEqualsTo(int v) { //Satisfied("userId", v); } private class Standard { } private class ThreadPool { //to be performant private int maxSize = 5; private List threads = new List (); private volatile Action _runable; private void StartNew(Action action) { this._runable = action; if (threads.Count < maxSize) { var t = new Thread(() => { while (true) { _runable(); Thread.CurrentThread.Suspend(); } }); t.Start(); threads.Add(t); } else { //exceed equal maxSize var t = threads.First(a => a.IsAlive && a.ThreadState != System.Threading.ThreadState.Running); t.Resume(); } } } private class ConnectionPool : IDisposable { private List pool = new List (); private int maxSize = 5; private DbConnection GetOpenConnection() { if (pool.Count < maxSize) { var conn = new SqlConnection(); pool.Add(conn); return conn; } else { if (!pool.Any(t => t.State != System.Data.ConnectionState.Open)) { throw new DBConcurrencyException("Max reached, no idle connection."); } //==maxSize return pool.First(c => c.State != System.Data.ConnectionState.Open); } } private bool _disposed = false; protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { pool.ForEach(c => c.Dispose()); } pool.Clear(); _disposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } ~ConnectionPool() { Dispose(false); } } public class Singleton where T : new() { private Singleton() { } public static T Instance = new T(); } public class Cache : ConcurrentDictionary<string, object> { } } } }