csharp-thread

Task and Thread

Task的背后的实现也是使用了线程池线程,但它的性能优于ThreadPoll,因为它使用的不是线程池的全局队列,而是使用的本地队列,使线程之间的资源竞争减少。同时Task提供了丰富的API来管理线程、控制。但是相对前面的两种耗内存,Task依赖于CPU对于多核的CPU性能远超前两者,单核的CPU三者的性能没什么差别。

Task.Run 和 Task.Factory.StartNew 里面有异常的时候都是不会抛出来的,需要在内部捕获

WaitAll is a blocking call
WhenAll - not - code will continue executing

Task

private Task taskPythonPlugin;

taskPythonPlugin = new Task(() =>
{
Console.WriteLine("task start");
task_pyton_plugin();
});

taskPythonPlugin.Start();

public void task_pyton_plugin()
{
}
var testTask = new Task(() =>
{
    Console.WriteLine("task start");
    System.Threading.Thread.Sleep(2000);
});
testTask.Start();
testTask.Wait();

Task.Run 和 Task.Factory.StartNew

异步串联多个任务

class Program
{
/* coder:释迦苦僧 */
static void Main(string[] args)
{
/*创建任务t1*/
Task t1 = Task.Factory.StartNew(() =>
{
Console.WriteLine("执行 t1 任务");
SpinWait.SpinUntil(() =>
{
return false;
}, 2000);

});
/*创建任务t2 t2任务的执行 依赖与t1任务的执行完成*/
Task t2 = t1.ContinueWith((t) =>
{
Console.WriteLine("执行 t2 任务");
SpinWait.SpinUntil(() =>
{
return false;
}, 2000);

});
/*创建任务t3 t3任务的执行 依赖与t2任务的执行完成*/
Task t3 = t2.ContinueWith((t) =>
{
Console.WriteLine("执行 t3 任务");
});
Console.ReadLine();
}
}
20200629_161706.png

thread

等待延时

System.Threading.Thread.Sleep(numberOfMilliseconds);

同步

// true signaled; false  non-signaled
AutoResetEvent autoResetEvent = new AutoResetEvent(false);

// true signaled; false non-signaled
ManualResetEvent manualResetEventPlcHeartbeat = new ManualResetEvent(true);

autoResetEvent.WaitOne();

autoResetEvent.Set();
autoResetEvent.Reset();

lock statment

msdn

// 访问PLC同步锁
private readonly object LockAccess = new object();
lock (LockAccess)
{
...
}

kill

// name without .exe
foreach (var process in Process.GetProcessesByName("whatever"))
{
process.Kill();
}

获取指定进程路径

// name without .exe
foreach (var process in Process.GetProcessesByName("nisedit"))
{
// 获取路径
spc_path = new FileInfo(process.MainModule.FileName).Directory.FullName;
// 完整路径包括文件名
var ss = process.MainModule.FileName;
// 获取路径,不包括文件名
ss = new FileInfo(spc_path).Directory.FullName;
process.Kill();
}

进程通讯

REST, gRPC


调用外部进程

try
{
// call python plugin
Process p = new Process();
p.StartInfo = new ProcessStartInfo(App.appPath + @"\plugin\python_plugin.exe");
p.StartInfo.Arguments = App.appPath + @"\plugin\run.py";
p.StartInfo.WorkingDirectory = App.appPath + @"\plugin\";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.UseShellExecute = false;
p.Start();
}catch(Exception ex)
{
Log.Error("load python plugin failed. " + ex.Message);
}

调用 cmd 执行命令

try
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = $"/C {storeExcelPath}";
startInfo.Verb = "runas";
startInfo.CreateNoWindow = true;
// 想使用管理员权限,这里必须是 true
startInfo.UseShellExecute = true;
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
process.Close();

tb_status.Text = "状态:正在打开Excel文档";
statusTimer.Start();
}
catch (Exception ex)
{
Log.Error("load python plugin failed. " + ex.Message);
MessageBox.Show($"打开文档失败 msg={ex.Message}");
}

调用外部进程获取返回值

// Synchronous example
static void runCommand()
{
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c DIR"; // Note the /c command (*)
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.Start();
//* Read the output (or the error)
string output = process.StandardOutput.ReadToEnd();
Console.WriteLine(output);
string err = process.StandardError.ReadToEnd();
Console.WriteLine(err);
process.WaitForExit();
}

// (*) For some commands (here StartInfo.Arguments) you must add the /c directive, otherwise the process freezes in the WaitForExit().

// Asynchronous example
static void runCommand()
{
//* Create your Process
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c DIR";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
//* Set your output and error (asynchronous) handlers
process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
//* Start process and handlers
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
}

static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
//* Do your stuff with the output (write to console/log/StringBuilder)
Console.WriteLine(outLine.Data);
}