<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns="http://purl.org/rss/1.0/">
<channel rdf:about="https://www.rickw.cn/">
<title>Rick &#039;s BLOG</title>
<link>https://www.rickw.cn/</link>
<description>Rick &#039;s BLOG</description>
<dc:language>zh-cn</dc:language>
<dc:creator>redcheek@gmail.com</dc:creator>
<items>
<rdf:Seq>
<item rdf:about="https://www.rickw.cn/blogview/339">
<title><![CDATA[C#实现WebApi接口数据传输加密方案]]></title>
	
<description><![CDATA[在项目开发中我们经常会调用接口或者实现一套webapi接口；<br />
如果项目要上线到公网中，那么我们就需要考虑安全问题；<br />
即便是在内网使用，安全问题也同样不能忽视。<br />
如果没有一套安全方案，那么我们的服务很有可能会被攻击。<br />
<br />]]></description>
<content:encoded><![CDATA[在项目开发中我们经常会调用接口或者实现一套webapi接口；<br />
如果项目要上线到公网中，那么我们就需要考虑安全问题；<br />
即便是在内网使用，安全问题也同样不能忽视。<br />
如果没有一套安全方案，那么我们的服务很有可能会被攻击。<br />
<br />
安全方案主要有加签名进行数据效验、传输数据加密等。<br />
<br />
<h2>1、加签SHA256</h2><br />
<div class="txt_main">public static string GetSHA256Hash(string input)<br />
{<br />
	using&nbsp;(SHA256 sha256Hash&nbsp;= SHA256.Create())<br />
	{<br />
		byte[]&nbsp;bytes&nbsp;=&nbsp;sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(input));<br />
		StringBuilder builder&nbsp;= new StringBuilder();<br />
		for (int&nbsp;i&nbsp;= 0;&nbsp;i&nbsp;&lt;&nbsp;bytes.Length;&nbsp;i++)<br />
		{<br />
			builder.Append(bytes[i].ToString("x2"));<br />
		}<br />
		return builder.ToString();<br />
	}<br />
}<br />
</div><br />
<br />
<h2>2、RSA加密/解密</h2><br />
<div class="txt_main">private&nbsp;readonly&nbsp;RSA&nbsp;_privateKeyRsaProvider;<br />
private&nbsp;readonly&nbsp;RSA&nbsp;_publicKeyRsaProvider;<br />
private&nbsp;readonly&nbsp;Encoding&nbsp;_encoding;<br />
/// &lt;param&nbsp;name="encoding"&gt;编码类型&lt;/param&gt;<br />
/// &lt;param&nbsp;name="privateKey"&gt;私钥&lt;/param&gt;<br />
/// &lt;param&nbsp;name="publicKey"&gt;公钥&lt;/param&gt;<br />
public&nbsp;RSAHelper(Encoding&nbsp;encoding,&nbsp;string&nbsp;privateKey,&nbsp;string&nbsp;publicKey&nbsp;=&nbsp;null)<br />
{<br />
	_encoding&nbsp;=&nbsp;encoding;<br />
	if&nbsp;(!string.IsNullOrEmpty(privateKey))<br />
	{<br />
		_privateKeyRsaProvider&nbsp;=&nbsp;CreateRsaProviderFromPrivateKey(privateKey);<br />
	}<br />
	if&nbsp;(!string.IsNullOrEmpty(publicKey))<br />
	{<br />
		_publicKeyRsaProvider&nbsp;=&nbsp;CreateRsaProviderFromPublicKey(publicKey);<br />
	}<br />
}<br />
//解密<br />
public&nbsp;string&nbsp;Decrypt(string&nbsp;cipherText)<br />
{<br />
	if&nbsp;(_privateKeyRsaProvider&nbsp;==&nbsp;null)<br />
	{<br />
		throw&nbsp;new&nbsp;Exception("_privateKeyRsaProvider&nbsp;is&nbsp;null");<br />
	}<br />
	return&nbsp;Encoding.UTF8.GetString(_privateKeyRsaProvider.Decrypt(Convert.FromBase64String(cipherText),&nbsp;RSAEncryptionPadding.Pkcs1));<br />
}<br />
//加密<br />
public&nbsp;string&nbsp;Encrypt(string&nbsp;text)<br />
{<br />
	if&nbsp;(_publicKeyRsaProvider&nbsp;==&nbsp;null)<br />
	{<br />
		throw&nbsp;new&nbsp;Exception("_publicKeyRsaProvider&nbsp;is&nbsp;null");<br />
	}<br />
	return&nbsp;Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(Encoding.UTF8.GetBytes(text),&nbsp;RSAEncryptionPadding.Pkcs1));<br />
}<br />
</div><br />
<br />
<h2>3、AES加密/解密</h2><br />
<div class="txt_main">/// &lt;summary&gt;<br />
///&nbsp;加密不带偏移量<br />
/// &lt;/summary&gt;<br />
/// &lt;param&nbsp;name="input"&gt;&lt;/param&gt;<br />
/// &lt;param&nbsp;name="key"&gt;秘钥&lt;/param&gt;<br />
/// &lt;returns&gt;&lt;/returns&gt;<br />
public&nbsp;static&nbsp;string&nbsp;EncryptByAES(string&nbsp;input,&nbsp;string&nbsp;key)<br />
{<br />
	if&nbsp;(string.IsNullOrWhiteSpace(input))<br />
	{<br />
		return&nbsp;input;<br />
	}<br />
	using&nbsp;(RijndaelManaged&nbsp;rijndaelManaged&nbsp;=&nbsp;new&nbsp;RijndaelManaged())<br />
	{<br />
		rijndaelManaged.Mode&nbsp;=&nbsp;CipherMode.ECB;<br />
		rijndaelManaged.Padding&nbsp;=&nbsp;PaddingMode.PKCS7;<br />
		rijndaelManaged.FeedbackSize&nbsp;=&nbsp;128;<br />
		byte[]&nbsp;data3&nbsp;=&nbsp;Enumerable.Range(0,&nbsp;key.Length&nbsp;/&nbsp;2).Select(x&nbsp;=&gt;&nbsp;Byte.Parse(key.Substring(x&nbsp;*&nbsp;2,&nbsp;2),&nbsp;NumberStyles.HexNumber)).ToArray();<br />
		rijndaelManaged.Key&nbsp;=&nbsp;data3;<br />
		ICryptoTransform&nbsp;encryptor&nbsp;=&nbsp;rijndaelManaged.CreateEncryptor(rijndaelManaged.Key,&nbsp;rijndaelManaged.IV);<br />
		using&nbsp;(MemoryStream&nbsp;msEncrypt&nbsp;=&nbsp;new&nbsp;MemoryStream())<br />
		{<br />
			using&nbsp;(CryptoStream&nbsp;csEncrypt&nbsp;=&nbsp;new&nbsp;CryptoStream(msEncrypt,&nbsp;encryptor,&nbsp;CryptoStreamMode.Write))	<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
				using&nbsp;(StreamWriter&nbsp;swEncrypt&nbsp;=&nbsp;new&nbsp;StreamWriter(csEncrypt))<br />
				{<br />
					swEncrypt.Write(input);<br />
				}<br />
				byte[]&nbsp;bytes&nbsp;=&nbsp;msEncrypt.ToArray();<br />
				//return&nbsp;Convert.ToBase64String(bytes);<br />
				return&nbsp;HexConvert.byteToHexStr(bytes);<br />
			}<br />
		}<br />
	}<br />
}<br />
</div><br />
<div class="txt_main">/// &lt;summary&gt;<br />
///&nbsp;返回解密后的字符串<br />
/// &lt;/summary&gt;<br />
/// &lt;param&nbsp;name="input"&gt;&lt;/param&gt;<br />
/// &lt;param&nbsp;name="key"&gt;秘钥&lt;/param&gt;<br />
/// &lt;returns&gt;&lt;/returns&gt;<br />
public&nbsp;static&nbsp;string&nbsp;DecryptByAES(string&nbsp;input,&nbsp;string&nbsp;key)<br />
{<br />
	if&nbsp;(string.IsNullOrWhiteSpace(input))<br />
	{<br />
		return&nbsp;input;<br />
	}<br />
	//var&nbsp;buffer&nbsp;=&nbsp;Convert.FromBase64String(input);<br />
	var&nbsp;buffer&nbsp;=&nbsp;HexConvert.strToToHexByte(input);<br />
	using&nbsp;(RijndaelManaged&nbsp;rijndaelManaged&nbsp;=&nbsp;new&nbsp;RijndaelManaged())<br />
	{<br />
		rijndaelManaged.Mode&nbsp;=&nbsp;CipherMode.ECB;<br />
		rijndaelManaged.Padding&nbsp;=&nbsp;PaddingMode.PKCS7;<br />
		rijndaelManaged.FeedbackSize&nbsp;=&nbsp;128;<br />
		byte[]&nbsp;data3&nbsp;=&nbsp;Enumerable.Range(0,&nbsp;key.Length&nbsp;/&nbsp;2).Select(x&nbsp;=&gt;&nbsp;Byte.Parse(key.Substring(x&nbsp;*&nbsp;2,&nbsp;2),&nbsp;NumberStyles.HexNumber)).ToArray();<br />
		rijndaelManaged.Key&nbsp;=&nbsp;data3;<br />
		ICryptoTransform&nbsp;decryptor&nbsp;=&nbsp;rijndaelManaged.CreateDecryptor(rijndaelManaged.Key,&nbsp;rijndaelManaged.IV);<br />
		using&nbsp;(MemoryStream&nbsp;msEncrypt&nbsp;=&nbsp;new&nbsp;MemoryStream(buffer))<br />
		{<br />
			using&nbsp;(CryptoStream&nbsp;csEncrypt&nbsp;=&nbsp;new&nbsp;CryptoStream(msEncrypt,&nbsp;decryptor,&nbsp;CryptoStreamMode.Read))<br />
			{<br />
				using&nbsp;(StreamReader&nbsp;srEncrypt&nbsp;=&nbsp;new&nbsp;StreamReader(csEncrypt))<br />
				{<br />
					return&nbsp;srEncrypt.ReadToEnd();<br />
				}<br />
			}<br />
		}<br />
	}<br />
}<br />
</div><br />
<br />
<h2>4、数据转换</h2><br />
<div class="txt_main">//字符串转换为字节数组<br />
byte[]&nbsp;originalBytes&nbsp;=&nbsp;System.Text.Encoding.UTF8.GetBytes(originalText);<br />
<br />
//&nbsp;进行Base64编码<br />
string&nbsp;base64Encoded&nbsp;=&nbsp;Convert.ToBase64String(originalBytes);<br />
<br />
//&nbsp;进行Base64解码<br />
byte[]&nbsp;base64DecodedBytes&nbsp;=&nbsp;Convert.FromBase64String(base64Encoded);<br />
<br />
//字节数组转字符串<br />
string&nbsp;base64DecodedText&nbsp;=&nbsp;System.Text.Encoding.UTF8.GetString(base64DecodedBytes);<br />
<br />
//16进制转base64字符串<br />
byte[]&nbsp;enterpriseCode_&nbsp;=&nbsp;HexConvert.strToToHexByte(data.enterpriseCode);<br />
string&nbsp;enterpriseCode&nbsp;=&nbsp;Convert.ToBase64String(enterpriseCode_);<br />
				<br />
/// &lt;summary&gt; <br />
///&nbsp;字节数组转16进制字符串 <br />
/// &lt;/summary&gt; <br />
/// &lt;param&nbsp;name="byteArray"&gt;&lt;/param&gt; <br />
/// &lt;returns&gt;&lt;/returns&gt; <br />
public&nbsp;static&nbsp;string&nbsp;byteToHexStr2(byte[]&nbsp;byteArray)<br />
{<br />
	string&nbsp;hexString&nbsp;=&nbsp;BitConverter.ToString(byteArray);<br />
	return&nbsp;hexString.Replace("-",&nbsp;"");<br />
}<br />
<br />
/// &lt;summary&gt; <br />
///&nbsp;字符串转16进制字节数组 <br />
/// &lt;/summary&gt; <br />
/// &lt;param&nbsp;name="hexString"&gt;&lt;/param&gt; <br />
/// &lt;returns&gt;&lt;/returns&gt; <br />
public&nbsp;static&nbsp;byte[]&nbsp;strToToHexByte(string&nbsp;hexString)<br />
{<br />
	hexString&nbsp;=&nbsp;hexString.Replace("&nbsp;",&nbsp;"");<br />
	if&nbsp;((hexString.Length&nbsp;%&nbsp;2)&nbsp;!=&nbsp;0)<br />
		hexString&nbsp;+=&nbsp;"&nbsp;";<br />
	byte[]&nbsp;returnBytes&nbsp;=&nbsp;new&nbsp;byte[hexString.Length&nbsp;/&nbsp;2];<br />
	for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;returnBytes.Length;&nbsp;i++)<br />
		returnBytes[i]&nbsp;=&nbsp;Convert.ToByte(hexString.Substring(i&nbsp;*&nbsp;2,&nbsp;2),&nbsp;16);<br />
	return&nbsp;returnBytes;<br />
}<br />
</div>]]></content:encoded>
<link>https://www.rickw.cn/blogview/339</link>
<dc:subject>C# .Net编程</dc:subject>
<dc:creator>rick</dc:creator>
<dc:date>2024-12-23 12:48:57</dc:date>
</item>
		
<item rdf:about="https://www.rickw.cn/blogview/332">
<title><![CDATA[C# 中实现几种幻灯片中的窗口特效]]></title>
	
<description><![CDATA[<ul><br />
<li>淡入淡出<br />
<li>变大变小<br />
<li>缓升缓降<br />
</ul></ol><br />]]></description>
<content:encoded><![CDATA[<ul><br />
<li>淡入淡出<br />
<li>变大变小<br />
<li>缓升缓降<br />
</ul></ol><br />
<br />
实现的代码片段参考如下：<br />
<br />
<strong>淡入淡出</strong><br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_Ej4bwMbQ6B6D')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_Ej4bwMbQ6B6D);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_Ej4bwMbQ6B6D" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #007700">public </span><span style="color: #0000BB">Form1</span><span style="color: #007700">()<br />
        {<br />
            </span><span style="color: #0000BB">InitializeComponent</span><span style="color: #007700">();<br />
            </span><span style="color: #0000BB">Opacity </span><span style="color: #007700">= </span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />
            </span><span style="color: #0000BB">timer1</span><span style="color: #007700">.</span><span style="color: #0000BB">Interval </span><span style="color: #007700">= </span><span style="color: #0000BB">10</span><span style="color: #007700">;<br />
            </span><span style="color: #0000BB">timer1</span><span style="color: #007700">.</span><span style="color: #0000BB">Start</span><span style="color: #007700">();<br />
        }<br />
   private </span><span style="color: #0000BB">void timer1_Tick</span><span style="color: #007700">(</span><span style="color: #0000BB">object sender</span><span style="color: #007700">, </span><span style="color: #0000BB">EventArgs e</span><span style="color: #007700">)<br />
        {<br />
<br />
            if (</span><span style="color: #0000BB">isShow</span><span style="color: #007700">)<br />
            {<br />
                if (</span><span style="color: #0000BB">Height </span><span style="color: #007700">&lt; </span><span style="color: #0000BB">height</span><span style="color: #007700">)<br />
                {<br />
                    </span><span style="color: #0000BB">Height </span><span style="color: #007700">+= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />
                }<br />
                else<br />
                {<br />
                    </span><span style="color: #0000BB">timer1</span><span style="color: #007700">.</span><span style="color: #0000BB">Stop</span><span style="color: #007700">();<br />
                }<br />
            }<br />
            else<br />
            {<br />
                if (</span><span style="color: #0000BB">ClientSize</span><span style="color: #007700">.</span><span style="color: #0000BB">Height </span><span style="color: #007700">&gt; </span><span style="color: #0000BB">0</span><span style="color: #007700">)<br />
                {<br />
                    </span><span style="color: #0000BB">Height </span><span style="color: #007700">-= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />
                }<br />
                else<br />
                {<br />
                    </span><span style="color: #0000BB">timer1</span><span style="color: #007700">.</span><span style="color: #0000BB">Stop</span><span style="color: #007700">();<br />
                    </span><span style="color: #0000BB">Close</span><span style="color: #007700">();<br />
                }<br />
            }<br />
        } </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
<br />
<strong>变大变小</strong><br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_S7Fdr1QUGznb')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_S7Fdr1QUGznb);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_S7Fdr1QUGznb" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #007700">public </span><span style="color: #0000BB">Form2</span><span style="color: #007700">()<br />
        {<br />
            </span><span style="color: #0000BB">InitializeComponent</span><span style="color: #007700">();<br />
            </span><span style="color: #0000BB">height </span><span style="color: #007700">= </span><span style="color: #0000BB">Height</span><span style="color: #007700">;<br />
<br />
            </span><span style="color: #0000BB">Size </span><span style="color: #007700">= new </span><span style="color: #0000BB">Size</span><span style="color: #007700">(</span><span style="color: #0000BB">Width</span><span style="color: #007700">, </span><span style="color: #0000BB">0</span><span style="color: #007700">);<br />
            </span><span style="color: #0000BB">timer1</span><span style="color: #007700">.</span><span style="color: #0000BB">Interval </span><span style="color: #007700">= </span><span style="color: #0000BB">10</span><span style="color: #007700">;<br />
            </span><span style="color: #0000BB">timer1</span><span style="color: #007700">.</span><span style="color: #0000BB">Start</span><span style="color: #007700">();<br />
        }<br />
 <br />
 private </span><span style="color: #0000BB">void timer1_Tick</span><span style="color: #007700">(</span><span style="color: #0000BB">object sender</span><span style="color: #007700">, </span><span style="color: #0000BB">EventArgs e</span><span style="color: #007700">)<br />
        {<br />
<br />
            if (</span><span style="color: #0000BB">isShow</span><span style="color: #007700">)<br />
            {<br />
                if (</span><span style="color: #0000BB">Height </span><span style="color: #007700">&lt; </span><span style="color: #0000BB">height</span><span style="color: #007700">)<br />
                {<br />
                    </span><span style="color: #0000BB">Height </span><span style="color: #007700">+= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />
                }<br />
                else<br />
                {<br />
                    </span><span style="color: #0000BB">timer1</span><span style="color: #007700">.</span><span style="color: #0000BB">Stop</span><span style="color: #007700">();<br />
                }<br />
            }<br />
            else<br />
            {<br />
                if (</span><span style="color: #0000BB">ClientSize</span><span style="color: #007700">.</span><span style="color: #0000BB">Height </span><span style="color: #007700">&gt; </span><span style="color: #0000BB">0</span><span style="color: #007700">)<br />
                {<br />
                    </span><span style="color: #0000BB">Height </span><span style="color: #007700">-= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />
                }<br />
                else<br />
                {<br />
                    </span><span style="color: #0000BB">timer1</span><span style="color: #007700">.</span><span style="color: #0000BB">Stop</span><span style="color: #007700">();<br />
                    </span><span style="color: #0000BB">Close</span><span style="color: #007700">();<br />
                }<br />
            }<br />
        } </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
<br />
<strong>缓升缓降</strong><br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_qp8FITOgcjkN')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_qp8FITOgcjkN);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_qp8FITOgcjkN" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #007700">public </span><span style="color: #0000BB">Form3</span><span style="color: #007700">()<br />
        {<br />
            </span><span style="color: #0000BB">InitializeComponent</span><span style="color: #007700">();<br />
            </span><span style="color: #0000BB">timer1</span><span style="color: #007700">.</span><span style="color: #0000BB">Interval </span><span style="color: #007700">= </span><span style="color: #0000BB">10</span><span style="color: #007700">;<br />
        }<br />
        private </span><span style="color: #0000BB">void Form3_Load</span><span style="color: #007700">(</span><span style="color: #0000BB">object sender</span><span style="color: #007700">, </span><span style="color: #0000BB">EventArgs e</span><span style="color: #007700">)<br />
        {<br />
            </span><span style="color: #0000BB">Location </span><span style="color: #007700">= new </span><span style="color: #0000BB">Point</span><span style="color: #007700">(</span><span style="color: #0000BB">screenRect</span><span style="color: #007700">.</span><span style="color: #0000BB">Width </span><span style="color: #007700">- </span><span style="color: #0000BB">Width</span><span style="color: #007700">, </span><span style="color: #0000BB">screenRect</span><span style="color: #007700">.</span><span style="color: #0000BB">Height</span><span style="color: #007700">);<br />
            </span><span style="color: #0000BB">timer1</span><span style="color: #007700">.</span><span style="color: #0000BB">Start</span><span style="color: #007700">();<br />
        }<br />
 private </span><span style="color: #0000BB">void timer1_Tick</span><span style="color: #007700">(</span><span style="color: #0000BB">object sender</span><span style="color: #007700">, </span><span style="color: #0000BB">EventArgs e</span><span style="color: #007700">)<br />
        {<br />
            if (</span><span style="color: #0000BB">isShow</span><span style="color: #007700">)<br />
            {<br />
                if (</span><span style="color: #0000BB">Location</span><span style="color: #007700">.</span><span style="color: #0000BB">Y </span><span style="color: #007700">&gt; </span><span style="color: #0000BB">screenRect</span><span style="color: #007700">.</span><span style="color: #0000BB">Height</span><span style="color: #007700">-</span><span style="color: #0000BB">Height</span><span style="color: #007700">)<br />
                {<br />
                    </span><span style="color: #0000BB">Location </span><span style="color: #007700">= new </span><span style="color: #0000BB">Point</span><span style="color: #007700">(</span><span style="color: #0000BB">Location</span><span style="color: #007700">.</span><span style="color: #0000BB">X</span><span style="color: #007700">, </span><span style="color: #0000BB">Location</span><span style="color: #007700">.</span><span style="color: #0000BB">Y </span><span style="color: #007700">- </span><span style="color: #0000BB">1</span><span style="color: #007700">);<br />
                }<br />
                else<br />
                {<br />
                    </span><span style="color: #0000BB">timer1</span><span style="color: #007700">.</span><span style="color: #0000BB">Stop</span><span style="color: #007700">();<br />
                }<br />
            }<br />
            else<br />
            {<br />
                if (</span><span style="color: #0000BB">Location</span><span style="color: #007700">.</span><span style="color: #0000BB">Y </span><span style="color: #007700">&lt; </span><span style="color: #0000BB">screenRect</span><span style="color: #007700">.</span><span style="color: #0000BB">Height </span><span style="color: #007700">)<br />
                {<br />
                    </span><span style="color: #0000BB">Location </span><span style="color: #007700">= new </span><span style="color: #0000BB">Point</span><span style="color: #007700">(</span><span style="color: #0000BB">Location</span><span style="color: #007700">.</span><span style="color: #0000BB">X</span><span style="color: #007700">, </span><span style="color: #0000BB">Location</span><span style="color: #007700">.</span><span style="color: #0000BB">Y </span><span style="color: #007700">+ </span><span style="color: #0000BB">1</span><span style="color: #007700">);<br />
                }<br />
                else<br />
                {<br />
                    </span><span style="color: #0000BB">timer1</span><span style="color: #007700">.</span><span style="color: #0000BB">Stop</span><span style="color: #007700">();<br />
                    </span><span style="color: #0000BB">Close</span><span style="color: #007700">();<br />
                }<br />
            }<br />
<br />
        } </span><span style="color: #0000BB">?&gt;</span></code></pre></div>]]></content:encoded>
<link>https://www.rickw.cn/blogview/332</link>
<dc:subject>C# .Net编程</dc:subject>
<dc:creator>rick</dc:creator>
<dc:date>2024-01-05 21:33:35</dc:date>
</item>
		
<item rdf:about="https://www.rickw.cn/blogview/324">
<title><![CDATA[C#中byte[]字节数组复制的5种常用方法]]></title>
	
<description><![CDATA[简单总结了5种字节数组的复制方法<br />
<br />
1、for循环实现复制<br />
较为原始的遍历写法，不太推荐<br />
<br />]]></description>
<content:encoded><![CDATA[简单总结了5种字节数组的复制方法<br />
<br />
1、for循环实现复制<br />
较为原始的遍历写法，不太推荐<br />
<br />
byte[]&nbsp;data&nbsp;=&nbsp;new&nbsp;byte[]{0,1,2,3,4,5,6,7,8,9};<br />
<br />
byte[]&nbsp;data1&nbsp;=&nbsp;new&nbsp;byte[data.length];<br />
<br />
for(int&nbsp;i=0;i&lt;data1.length;i++)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data1[i]&nbsp;=&nbsp;data[i];<br />
}<br />
2、Arrary.Copy实现复制<br />
在CLR处理机制中最灵活，最强大,可装箱，拆箱复制，可加宽CLR基元类型，可内部判断实现了IFarmattable接口的兼容转换，当然这种强大方式必然会带来一定的性能损失。还有个CopyTo也是一样的。<br />
<br />
byte[]&nbsp;data&nbsp;=&nbsp;new&nbsp;byte[]{0,1,2,3,4,5,6,7,8,9};<br />
byte[]&nbsp;data1&nbsp;=&nbsp;new&nbsp;byte[data.length];<br />
Array.Copy(data,data1,data.length);//源数据data，目标数据data1，复制长度data.length<br />
3、Clone实现复制<br />
Clone会创建新数组，分配内存，不宜用在需要保持高刷新率下的场景<br />
<br />
&nbsp;byte[]&nbsp;data&nbsp;=&nbsp;new&nbsp;byte[]{0,1,2,3,4,5,6,7,8,9};<br />
&nbsp;byte[]&nbsp;data1;<br />
&nbsp;data1&nbsp;=&nbsp;(byte[])data&nbsp;.Clone()<br />
4、Buffer.BlockCopy实现复制<br />
则从本质上以字节为复制单位，这在底层语言C，C++的处理优势上，同理，效率之高可以理解。当然如果对性能要求不高，Copy足矣，毕竟在上千次复制下，三者基本没消耗多少时间。使用时可根据项目需求斟酌选择！<br />
<br />
&nbsp;byte[]&nbsp;srcArray&nbsp;=&nbsp;new&nbsp;byte[]&nbsp;{&nbsp;0x01,&nbsp;0x02,&nbsp;0x03,&nbsp;0x04&nbsp;};<br />
&nbsp;byte[]&nbsp;dstArray&nbsp;=&nbsp;new&nbsp;byte[srcArray.Length];<br />
&nbsp;Buffer.BlockCopy(srcArray,&nbsp;0,&nbsp;dstArray,&nbsp;0,&nbsp;srcArray.Length);<br />
&nbsp;//源数据srcArray&nbsp;，&nbsp;起始位置0，目标数组dstArray&nbsp;，开始位置0，多少长度&nbsp;srcArray.Length<br />
5、Array.ConstrainedCopy&nbsp;实现复制<br />
对复制要求严格，只能是同类型或者源数组类型是目标类型的派生元素类型，不执行装箱，拆箱，向下转换。<br />
<br />
&nbsp;byte[]&nbsp;srcArray&nbsp;=&nbsp;new&nbsp;byte[]&nbsp;{&nbsp;0x01,&nbsp;0x02,&nbsp;0x03,&nbsp;0x04&nbsp;};<br />
&nbsp;byte[]&nbsp;dstArray&nbsp;=&nbsp;new&nbsp;byte[srcArray.Length];<br />
&nbsp;Array.ConstrainedCopy(srcArray,&nbsp;0,&nbsp;dstArray,&nbsp;0,&nbsp;srcArray.Length);<br />
&nbsp;//源数据srcArray&nbsp;，&nbsp;起始位置0，目标数组dstArray&nbsp;，开始位置0，多少长度&nbsp;srcArray.Length]]></content:encoded>
<link>https://www.rickw.cn/blogview/324</link>
<dc:subject>C# .Net编程</dc:subject>
<dc:creator>rick</dc:creator>
<dc:date>2023-12-27 11:17:44</dc:date>
</item>
		
<item rdf:about="https://www.rickw.cn/blogview/317">
<title><![CDATA[C# 使用 HttpClient错误？SocketException：现有连接被远程主机强行关闭]]></title>
	
<description><![CDATA[C#中使用&nbsp;HttpClient&nbsp;访问https站点，出现以下错误。<br />
<br />
System.AggregateException<br />
&nbsp;&nbsp;HResult&nbsp;=&nbsp;0x80131500<br />
&nbsp;&nbsp;Message&nbsp;=发生一个或多个错误。<br />]]></description>
<content:encoded><![CDATA[C#中使用&nbsp;HttpClient&nbsp;访问https站点，出现以下错误。<br />
<br />
System.AggregateException<br />
&nbsp;&nbsp;HResult&nbsp;=&nbsp;0x80131500<br />
&nbsp;&nbsp;Message&nbsp;=发生一个或多个错误。<br />
&nbsp;&nbsp;来源=&nbsp;System.Private.CoreLib<br />
&nbsp;&nbsp;堆栈跟踪：<br />
&nbsp;&nbsp;&nbsp;在System.Threading.Tasks.Task`1.GetResultCore（Boolean&nbsp;waitCompletionNotification）<br />
&nbsp;&nbsp;<br />
内部例外1：<br />
HttpRequestException：无法建立SSL连接，请参阅内部异常。<br />
<br />
内部例外2：<br />
IOException：无法从传输连接中读取数据：现有连接被远程主机强行关闭。<br />
<br />
内部例外3：<br />
SocketException：现有连接被远程主机强行关闭<br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_qc18vJm2UxMd')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_qc18vJm2UxMd);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_qc18vJm2UxMd" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #0000BB"><br />
</span><span style="color: #007700">class </span><span style="color: #0000BB">Program<br />
</span><span style="color: #007700">{<br />
    static </span><span style="color: #0000BB">void Main</span><span style="color: #007700">(</span><span style="color: #0000BB">string</span><span style="color: #007700">[] </span><span style="color: #0000BB">args</span><span style="color: #007700">)<br />
    {<br />
        var </span><span style="color: #0000BB">url </span><span style="color: #007700">= </span><span style="color: #DD0000">"https://google.com"</span><span style="color: #007700">;<br />
        var (</span><span style="color: #0000BB">statusCode</span><span style="color: #007700">, </span><span style="color: #0000BB">html</span><span style="color: #007700">) = </span><span style="color: #0000BB">requestString</span><span style="color: #007700">(</span><span style="color: #0000BB">url</span><span style="color: #007700">);<br />
        </span><span style="color: #0000BB">Console</span><span style="color: #007700">.</span><span style="color: #0000BB">WriteLine</span><span style="color: #007700">(</span><span style="color: #DD0000">"%d %s"</span><span style="color: #007700">, </span><span style="color: #0000BB">statusCode</span><span style="color: #007700">, </span><span style="color: #0000BB">html</span><span style="color: #007700">);<br />
    }<br />
<br />
    static </span><span style="color: #0000BB">CookieContainer cc </span><span style="color: #007700">= new </span><span style="color: #0000BB">CookieContainer</span><span style="color: #007700">();<br />
<br />
    static </span><span style="color: #0000BB">HttpClientHandler handler </span><span style="color: #007700">= new </span><span style="color: #0000BB">HttpClientHandler </span><span style="color: #007700">{ </span><span style="color: #0000BB">AllowAutoRedirect </span><span style="color: #007700">= </span><span style="color: #0000BB">false</span><span style="color: #007700">, </span><span style="color: #0000BB">CookieContainer </span><span style="color: #007700">= </span><span style="color: #0000BB">cc </span><span style="color: #007700">};<br />
<br />
    public static </span><span style="color: #0000BB">async Task</span><span style="color: #007700">&lt;(</span><span style="color: #0000BB">int statusCode</span><span style="color: #007700">, </span><span style="color: #0000BB">string content</span><span style="color: #007700">)&gt; </span><span style="color: #0000BB">requestStringAsync</span><span style="color: #007700">(</span><span style="color: #0000BB">string url</span><span style="color: #007700">)<br />
    {<br />
        </span><span style="color: #0000BB">ServicePointManager</span><span style="color: #007700">.</span><span style="color: #0000BB">ServerCertificateValidationCallback </span><span style="color: #007700">+= (</span><span style="color: #0000BB">sender</span><span style="color: #007700">, </span><span style="color: #0000BB">cert</span><span style="color: #007700">, </span><span style="color: #0000BB">chain</span><span style="color: #007700">, </span><span style="color: #0000BB">sslPolicyErrors</span><span style="color: #007700">) =&gt; </span><span style="color: #0000BB">true</span><span style="color: #007700">;<br />
        </span><span style="color: #0000BB">ServicePointManager</span><span style="color: #007700">.</span><span style="color: #0000BB">SecurityProtocol </span><span style="color: #007700">|= </span><span style="color: #0000BB">SecurityProtocolType</span><span style="color: #007700">.</span><span style="color: #0000BB">Tls </span><span style="color: #007700">| </span><span style="color: #0000BB">SecurityProtocolType</span><span style="color: #007700">.</span><span style="color: #0000BB">Tls11 </span><span style="color: #007700">| </span><span style="color: #0000BB">SecurityProtocolType</span><span style="color: #007700">.</span><span style="color: #0000BB">Tls12</span><span style="color: #007700">;<br />
                                                                     </span><span style="color: #FF8000">// | SecurityProtocolType.Ssl3;<br />
        </span><span style="color: #0000BB">using </span><span style="color: #007700">(var </span><span style="color: #0000BB">request </span><span style="color: #007700">= new </span><span style="color: #0000BB">HttpRequestMessage </span><span style="color: #007700">{ </span><span style="color: #0000BB">RequestUri </span><span style="color: #007700">= new </span><span style="color: #0000BB">Uri</span><span style="color: #007700">(</span><span style="color: #0000BB">url</span><span style="color: #007700">), </span><span style="color: #0000BB">Method </span><span style="color: #007700">= </span><span style="color: #0000BB">HttpMethod</span><span style="color: #007700">.</span><span style="color: #0000BB">Get </span><span style="color: #007700">})<br />
        </span><span style="color: #0000BB">using </span><span style="color: #007700">(var </span><span style="color: #0000BB">client </span><span style="color: #007700">= new </span><span style="color: #0000BB">HttpClient</span><span style="color: #007700">(</span><span style="color: #0000BB">handler</span><span style="color: #007700">))<br />
        {<br />
            var </span><span style="color: #0000BB">response </span><span style="color: #007700">= </span><span style="color: #0000BB">await client</span><span style="color: #007700">.</span><span style="color: #0000BB">SendAsync</span><span style="color: #007700">(</span><span style="color: #0000BB">request</span><span style="color: #007700">); </span><span style="color: #FF8000">// Error (actual line)<br />
         <br />
            </span><span style="color: #007700">var </span><span style="color: #0000BB">statusCode </span><span style="color: #007700">= (int)</span><span style="color: #0000BB">response</span><span style="color: #007700">.</span><span style="color: #0000BB">StatusCode</span><span style="color: #007700">;<br />
            var </span><span style="color: #0000BB">content </span><span style="color: #007700">= </span><span style="color: #0000BB">await response</span><span style="color: #007700">.</span><span style="color: #0000BB">Content</span><span style="color: #007700">.</span><span style="color: #0000BB">ReadAsStringAsync</span><span style="color: #007700">();<br />
            return (</span><span style="color: #0000BB">statusCode</span><span style="color: #007700">, </span><span style="color: #0000BB">content</span><span style="color: #007700">);<br />
        }<br />
    }<br />
<br />
    public static (</span><span style="color: #0000BB">int statusCode</span><span style="color: #007700">, </span><span style="color: #0000BB">string content</span><span style="color: #007700">) </span><span style="color: #0000BB">requestString</span><span style="color: #007700">(</span><span style="color: #0000BB">string url</span><span style="color: #007700">)<br />
    {<br />
        return </span><span style="color: #0000BB">requestStringAsync</span><span style="color: #007700">(</span><span style="color: #0000BB">url</span><span style="color: #007700">).</span><span style="color: #0000BB">Result</span><span style="color: #007700">;<br />
    }<br />
} </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
<br />
按上面调整&nbsp;ServicePointManager&nbsp;后在&nbsp;.net&nbsp;framework环境中就可以正常运行了。<br />
<br />
在.Net&nbsp;Core的环境中还可能发生问题。<br />
<br />
.Net&nbsp;Core中可以使用以下机制之一来配置进程以使用较旧的HttpClientHandler：<br />
<br />
从代码中，使用AppContext类：<br />
<br />
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler",&nbsp;false);<br />
<br />
也可以通过配置文件来设置AppContext开关。<br />
<br />
可以通过环境变量DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER实现相同的目的。<br />
要选择退出，请将值设置为false或0。]]></content:encoded>
<link>https://www.rickw.cn/blogview/317</link>
<dc:subject>C# .Net编程</dc:subject>
<dc:creator>rick</dc:creator>
<dc:date>2023-12-22 00:17:40</dc:date>
</item>
		
<item rdf:about="https://www.rickw.cn/blogview/316">
<title><![CDATA[C#屏幕截图，指定区域截图，窗口截图的实现]]></title>
	
<description><![CDATA[核心方法是使用Graphics类的CopyFromScreen方法将窗口的内容复制到位图中。<br />
指定区域截图，只需要将屏幕图片按区域裁剪即可。<br />
指定窗口截图，先获取窗口的位置和大小，然后转化为指定区域截图了。<br />
如果是制作指定窗口的录屏程序时，需要注意实时跟踪窗口的位置和大小（窗口位置和大小可能会调整变化）。<br />
其它的就没有特别的了。<br />]]></description>
<content:encoded><![CDATA[核心方法是使用Graphics类的CopyFromScreen方法将窗口的内容复制到位图中。<br />
指定区域截图，只需要将屏幕图片按区域裁剪即可。<br />
指定窗口截图，先获取窗口的位置和大小，然后转化为指定区域截图了。<br />
如果是制作指定窗口的录屏程序时，需要注意实时跟踪窗口的位置和大小（窗口位置和大小可能会调整变化）。<br />
其它的就没有特别的了。<br />
<br />
例子代码：<br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_7SDXIM968X8W')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_7SDXIM968X8W);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_7SDXIM968X8W" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #0000BB">using System</span><span style="color: #007700">;<br />
</span><span style="color: #0000BB">using System</span><span style="color: #007700">.</span><span style="color: #0000BB">Drawing</span><span style="color: #007700">;<br />
</span><span style="color: #0000BB">using System</span><span style="color: #007700">.</span><span style="color: #0000BB">Runtime</span><span style="color: #007700">.</span><span style="color: #0000BB">InteropServices</span><span style="color: #007700">;<br />
<br />
class </span><span style="color: #0000BB">Program<br />
</span><span style="color: #007700">{<br />
    [</span><span style="color: #0000BB">DllImport</span><span style="color: #007700">(</span><span style="color: #DD0000">"user32.dll"</span><span style="color: #007700">)]<br />
    static </span><span style="color: #0000BB">extern IntPtr GetForegroundWindow</span><span style="color: #007700">();<br />
<br />
    [</span><span style="color: #0000BB">DllImport</span><span style="color: #007700">(</span><span style="color: #DD0000">"user32.dll"</span><span style="color: #007700">)]<br />
    [return: </span><span style="color: #0000BB">MarshalAs</span><span style="color: #007700">(</span><span style="color: #0000BB">UnmanagedType</span><span style="color: #007700">.</span><span style="color: #0000BB">Bool</span><span style="color: #007700">)]<br />
    static </span><span style="color: #0000BB">extern bool GetWindowRect</span><span style="color: #007700">(</span><span style="color: #0000BB">IntPtr hWnd</span><span style="color: #007700">, </span><span style="color: #0000BB">out RECT lpRect</span><span style="color: #007700">);<br />
<br />
    [</span><span style="color: #0000BB">StructLayout</span><span style="color: #007700">(</span><span style="color: #0000BB">LayoutKind</span><span style="color: #007700">.</span><span style="color: #0000BB">Sequential</span><span style="color: #007700">)]<br />
    public </span><span style="color: #0000BB">struct RECT<br />
    </span><span style="color: #007700">{<br />
        public </span><span style="color: #0000BB">int Left</span><span style="color: #007700">;<br />
        public </span><span style="color: #0000BB">int Top</span><span style="color: #007700">;<br />
        public </span><span style="color: #0000BB">int Right</span><span style="color: #007700">;<br />
        public </span><span style="color: #0000BB">int Bottom</span><span style="color: #007700">;<br />
    }<br />
<br />
    static </span><span style="color: #0000BB">void Main</span><span style="color: #007700">()<br />
    {<br />
        try<br />
        {<br />
            </span><span style="color: #FF8000">// 获取活动窗口句柄<br />
            </span><span style="color: #0000BB">IntPtr hWnd </span><span style="color: #007700">= </span><span style="color: #0000BB">GetForegroundWindow</span><span style="color: #007700">();<br />
<br />
            </span><span style="color: #FF8000">// 获取窗口位置和大小<br />
            </span><span style="color: #0000BB">RECT windowRect</span><span style="color: #007700">;<br />
            </span><span style="color: #0000BB">GetWindowRect</span><span style="color: #007700">(</span><span style="color: #0000BB">hWnd</span><span style="color: #007700">, </span><span style="color: #0000BB">out windowRect</span><span style="color: #007700">);<br />
<br />
            </span><span style="color: #FF8000">// 创建Bitmap对象<br />
            </span><span style="color: #0000BB">using </span><span style="color: #007700">(</span><span style="color: #0000BB">Bitmap bmp </span><span style="color: #007700">= new </span><span style="color: #0000BB">Bitmap</span><span style="color: #007700">(</span><span style="color: #0000BB">windowRect</span><span style="color: #007700">.</span><span style="color: #0000BB">Right </span><span style="color: #007700">- </span><span style="color: #0000BB">windowRect</span><span style="color: #007700">.</span><span style="color: #0000BB">Left</span><span style="color: #007700">, </span><span style="color: #0000BB">windowRect</span><span style="color: #007700">.</span><span style="color: #0000BB">Bottom </span><span style="color: #007700">- </span><span style="color: #0000BB">windowRect</span><span style="color: #007700">.</span><span style="color: #0000BB">Top</span><span style="color: #007700">))<br />
            {<br />
                </span><span style="color: #FF8000">// 创建Graphics对象<br />
                </span><span style="color: #0000BB">using </span><span style="color: #007700">(</span><span style="color: #0000BB">Graphics g </span><span style="color: #007700">= </span><span style="color: #0000BB">Graphics</span><span style="color: #007700">.</span><span style="color: #0000BB">FromImage</span><span style="color: #007700">(</span><span style="color: #0000BB">bmp</span><span style="color: #007700">))<br />
                {<br />
                    </span><span style="color: #FF8000">// 将窗口内容绘制到Bitmap中<br />
                    // 这里可以直接指定位置和大小进行图片截取拷贝<br />
                    </span><span style="color: #0000BB">g</span><span style="color: #007700">.</span><span style="color: #0000BB">CopyFromScreen</span><span style="color: #007700">(new </span><span style="color: #0000BB">Point</span><span style="color: #007700">(</span><span style="color: #0000BB">windowRect</span><span style="color: #007700">.</span><span style="color: #0000BB">Left</span><span style="color: #007700">, </span><span style="color: #0000BB">windowRect</span><span style="color: #007700">.</span><span style="color: #0000BB">Top</span><span style="color: #007700">), </span><span style="color: #0000BB">Point</span><span style="color: #007700">.Empty, </span><span style="color: #0000BB">bmp</span><span style="color: #007700">.</span><span style="color: #0000BB">Size</span><span style="color: #007700">);<br />
                }<br />
<br />
                </span><span style="color: #FF8000">// 保存屏幕截图（可根据需要进行保存）<br />
                </span><span style="color: #0000BB">bmp</span><span style="color: #007700">.</span><span style="color: #0000BB">Save</span><span style="color: #007700">(</span><span style="color: #DD0000">"screenshot.png"</span><span style="color: #007700">);<br />
                <br />
                </span><span style="color: #0000BB">Console</span><span style="color: #007700">.</span><span style="color: #0000BB">WriteLine</span><span style="color: #007700">(</span><span style="color: #DD0000">"屏幕截图已保存成功。"</span><span style="color: #007700">);<br />
            }<br />
        }<br />
        catch (</span><span style="color: #0000BB">Exception ex</span><span style="color: #007700">)<br />
        {<br />
            </span><span style="color: #0000BB">Console</span><span style="color: #007700">.</span><span style="color: #0000BB">WriteLine</span><span style="color: #007700">(</span><span style="color: #DD0000">"发生异常：" </span><span style="color: #007700">+ </span><span style="color: #0000BB">ex</span><span style="color: #007700">.</span><span style="color: #0000BB">Message</span><span style="color: #007700">);<br />
        }<br />
    }<br />
} </span><span style="color: #0000BB">?&gt;</span></code></pre></div>]]></content:encoded>
<link>https://www.rickw.cn/blogview/316</link>
<dc:subject>C# .Net编程</dc:subject>
<dc:creator>rick</dc:creator>
<dc:date>2023-12-21 12:11:46</dc:date>
</item>
		
<item rdf:about="https://www.rickw.cn/blogview/310">
<title><![CDATA[C#同步代码中调用async异步方法.Result等待导致阻塞死锁deadlock的问题]]></title>
	
<description><![CDATA[在&nbsp;UI界面或者ASP.NET的同步代码中调用async的异步代码时如果async和task.Result混用会出现线程被阻塞锁死deadlock的情况。<br />
<strong>导致死锁的例子代码：</strong><br />
<div class="txt_main">public&nbsp;static&nbsp;async&nbsp;Task&lt;string&gt;&nbsp;GetWebPageAsync(string&nbsp;uri)<br />
{<br />
&nbsp;&nbsp;//这里的&nbsp;client&nbsp;是全局初始化的&nbsp;HttpClient&nbsp;对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;&nbsp;=&nbsp;await&nbsp;client.GetStringAsync(uri);<br />
}<br />
<br />
public&nbsp;void&nbsp;Button1_Click(object&nbsp;sender,&nbsp;EventArg&nbsp;e)<br />
{<br />
&nbsp;&nbsp;var&nbsp;webTask&nbsp;=&nbsp;GetWebPageAsync("_get_url_");<br />
&nbsp;&nbsp;textBox1.Text&nbsp;=&nbsp;webTask.Result;<br />
}</div><br />
]]></description>
<content:encoded><![CDATA[在&nbsp;UI界面或者ASP.NET的同步代码中调用async的异步代码时如果async和task.Result混用会出现线程被阻塞锁死deadlock的情况。<br />
<strong>导致死锁的例子代码：</strong><br />
<div class="txt_main">public&nbsp;static&nbsp;async&nbsp;Task&lt;string&gt;&nbsp;GetWebPageAsync(string&nbsp;uri)<br />
{<br />
&nbsp;&nbsp;//这里的&nbsp;client&nbsp;是全局初始化的&nbsp;HttpClient&nbsp;对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;&nbsp;=&nbsp;await&nbsp;client.GetStringAsync(uri);<br />
}<br />
<br />
public&nbsp;void&nbsp;Button1_Click(object&nbsp;sender,&nbsp;EventArg&nbsp;e)<br />
{<br />
&nbsp;&nbsp;var&nbsp;webTask&nbsp;=&nbsp;GetWebPageAsync("_get_url_");<br />
&nbsp;&nbsp;textBox1.Text&nbsp;=&nbsp;webTask.Result;<br />
}</div><br />
<br />
<br />
<h2>阻止死锁的两种办法：</h2><br />
<div class="txt_main"><strong>一、使用&nbsp;ConfigureAwait(false)</strong><br />
<div class="txt_main">public&nbsp;static&nbsp;async&nbsp;Task&lt;string&gt;&nbsp;GetWebPageAsync(string&nbsp;uri)<br />
{<br />
&nbsp;&nbsp;//这里的&nbsp;client&nbsp;是全局初始化的&nbsp;HttpClient&nbsp;对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;&nbsp;=&nbsp;await&nbsp;client.GetStringAsync(uri)<font color="red">.ConfigureAwait(false)</font>;<br />
}</div><br />
<br />
<div class="code_head"></div><div class="code_main quote"><blockquote>默认情况下，当您使用async/await时，它将在开始请求的原始线程上继续运行(状态机)。但是，如果当前另一个长时间运行的进程已经接管了该线程，那么你就不得不等待它完成。要避免这个问题，可以使用ConfigureAwait的方法和false参数。当你用这个方法的时候，这将告诉Task它可以在任何可用的线程上恢复自己继续运行，而不是等待最初创建它的线程。这将加快响应速度并避免许多死锁。<br />
<br />
但是，当使用此方法后，线程同步上下文将丢失，从而转变成异步操作，如果在之后继续操作界面元素等，会提示线程不安全。</blockquote></div><br />
<br />
<strong>二、使用&nbsp;异步Async&nbsp;方法进行调用：</strong><br />
<div class="txt_main">public&nbsp;<font color="red">async</font>&nbsp;void&nbsp;Button1_Click(object&nbsp;sender,&nbsp;EventArg&nbsp;e)<br />
{<br />
&nbsp;&nbsp;var&nbsp;webTask&nbsp;=&nbsp;GetWebPageAsync("_get_url_");<br />
&nbsp;&nbsp;textBox1.Text&nbsp;=&nbsp;webTask.Result;<br />
}</div><br />
</div>]]></content:encoded>
<link>https://www.rickw.cn/blogview/310</link>
<dc:subject>C# .Net编程</dc:subject>
<dc:creator>rick</dc:creator>
<dc:date>2023-12-17 11:34:09</dc:date>
</item>
		
<item rdf:about="https://www.rickw.cn/blogview/300">
<title><![CDATA[解决C#编译问题 CS 1617：/langversion的选项“10”无效]]></title>
	
<description><![CDATA[这个选项是开启C#10的语言特性支持。<br />
和VS版本有关，如果你使用的是VS2019，那么关闭项目，用文本打开csproj文件，将&lt;LangVersion&gt;10.0&lt;/LangVersion&gt;改为&lt;LangVersion&gt;9.0&lt;/LangVersion&gt;<br />
<br />
或者升级使用VS&nbsp;2022打开项目进行编译。<br />
]]></description>
<content:encoded><![CDATA[在&nbsp;UI界面或者ASP.NET的同步代码中调用async的异步代码时如果async和task.Result混用会出现线程被阻塞锁死deadlock的情况。<br />
<strong>导致死锁的例子代码：</strong><br />
<div class="txt_main">public&nbsp;static&nbsp;async&nbsp;Task&lt;string&gt;&nbsp;GetWebPageAsync(string&nbsp;uri)<br />
{<br />
&nbsp;&nbsp;//这里的&nbsp;client&nbsp;是全局初始化的&nbsp;HttpClient&nbsp;对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;&nbsp;=&nbsp;await&nbsp;client.GetStringAsync(uri);<br />
}<br />
<br />
public&nbsp;void&nbsp;Button1_Click(object&nbsp;sender,&nbsp;EventArg&nbsp;e)<br />
{<br />
&nbsp;&nbsp;var&nbsp;webTask&nbsp;=&nbsp;GetWebPageAsync("_get_url_");<br />
&nbsp;&nbsp;textBox1.Text&nbsp;=&nbsp;webTask.Result;<br />
}</div><br />
<br />
<br />
<h2>阻止死锁的两种办法：</h2><br />
<div class="txt_main"><strong>一、使用&nbsp;ConfigureAwait(false)</strong><br />
<div class="txt_main">public&nbsp;static&nbsp;async&nbsp;Task&lt;string&gt;&nbsp;GetWebPageAsync(string&nbsp;uri)<br />
{<br />
&nbsp;&nbsp;//这里的&nbsp;client&nbsp;是全局初始化的&nbsp;HttpClient&nbsp;对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;&nbsp;=&nbsp;await&nbsp;client.GetStringAsync(uri)<font color="red">.ConfigureAwait(false)</font>;<br />
}</div><br />
<br />
<div class="code_head"></div><div class="code_main quote"><blockquote>默认情况下，当您使用async/await时，它将在开始请求的原始线程上继续运行(状态机)。但是，如果当前另一个长时间运行的进程已经接管了该线程，那么你就不得不等待它完成。要避免这个问题，可以使用ConfigureAwait的方法和false参数。当你用这个方法的时候，这将告诉Task它可以在任何可用的线程上恢复自己继续运行，而不是等待最初创建它的线程。这将加快响应速度并避免许多死锁。<br />
<br />
但是，当使用此方法后，线程同步上下文将丢失，从而转变成异步操作，如果在之后继续操作界面元素等，会提示线程不安全。</blockquote></div><br />
<br />
<strong>二、使用&nbsp;异步Async&nbsp;方法进行调用：</strong><br />
<div class="txt_main">public&nbsp;<font color="red">async</font>&nbsp;void&nbsp;Button1_Click(object&nbsp;sender,&nbsp;EventArg&nbsp;e)<br />
{<br />
&nbsp;&nbsp;var&nbsp;webTask&nbsp;=&nbsp;GetWebPageAsync("_get_url_");<br />
&nbsp;&nbsp;textBox1.Text&nbsp;=&nbsp;webTask.Result;<br />
}</div><br />
</div>]]></content:encoded>
<link>https://www.rickw.cn/blogview/300</link>
<dc:subject>C# .Net编程</dc:subject>
<dc:creator>rick</dc:creator>
<dc:date>2023-12-10 11:58:25</dc:date>
</item>
		
<item rdf:about="https://www.rickw.cn/blogview/283">
<title><![CDATA[Jurassic [C# .Net JavaScript引擎]限制脚本执行时间，防止死循环]]></title>
	
<description><![CDATA[想象一下在js引擎中执行如下代码：<br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_Ve6Fsp4XXKdV')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_Ve6Fsp4XXKdV);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_Ve6Fsp4XXKdV" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #007700">try {}<br />
finally {<br />
    while (</span><span style="color: #0000BB">true</span><span style="color: #007700">);} </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_Ouo8Figz52Cm')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_Ouo8Figz52Cm);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_Ouo8Figz52Cm" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #0000BB"> </span><span style="color: #007700">while (</span><span style="color: #0000BB">true</span><span style="color: #007700">);  </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
这样一个无限循环的js代码在&nbsp;ScriptEngine.Execute(String&nbsp;code)的调用中将永远不会返回。<br />
]]></description>
<content:encoded><![CDATA[想象一下在js引擎中执行如下代码：<br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_mbUGZ75yBXsA')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_mbUGZ75yBXsA);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_mbUGZ75yBXsA" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #007700">try {}<br />
finally {<br />
    while (</span><span style="color: #0000BB">true</span><span style="color: #007700">);} </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_CxTvPfnzFPKK')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_CxTvPfnzFPKK);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_CxTvPfnzFPKK" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #0000BB"> </span><span style="color: #007700">while (</span><span style="color: #0000BB">true</span><span style="color: #007700">);  </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
这样一个无限循环的js代码在&nbsp;ScriptEngine.Execute(String&nbsp;code)的调用中将永远不会返回。<br />
<br />
Jurassic没有本身没有实现限制脚本执行时间的功能。由于Jurassic将JavaScript方法编译为IL代码，没有简单的方式来实现超时功能而不影响性能。但是，我们可以在执行脚本的线程中调用Thread.Abort()引发ThreadAbortException来终止脚本的执行。<br />
<h2>一种实现方式：</h2><br />
<div class="txt_main">在新线程中执行&nbsp;ScriptEngine.Execute()，在当前线程中进行等待并计时。当新线程在规定的时间内未完成，则在当前线程中调用<br />
thread.Abort()来终止新线程，并抛出一个超时的异常(TimeOutException)。<br />
</div><br />
<br />
<h2>用于限制脚本执行时间的Helper类（ScriptTimeoutHelper）</h2><br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_OSkSHv1BTfvU')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_OSkSHv1BTfvU);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_OSkSHv1BTfvU" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #0000BB">using System</span><span style="color: #007700">;<br />
</span><span style="color: #0000BB">using System</span><span style="color: #007700">.</span><span style="color: #0000BB">Runtime</span><span style="color: #007700">.</span><span style="color: #0000BB">ExceptionServices</span><span style="color: #007700">;<br />
</span><span style="color: #0000BB">using System</span><span style="color: #007700">.</span><span style="color: #0000BB">Threading</span><span style="color: #007700">;<br />
</span><span style="color: #0000BB">using System</span><span style="color: #007700">.</span><span style="color: #0000BB">Threading</span><span style="color: #007700">.</span><span style="color: #0000BB">Tasks</span><span style="color: #007700">;<br />
<br />
namespace </span><span style="color: #0000BB">JurassicTimeoutHelper<br />
</span><span style="color: #007700">{<br />
    </span><span style="color: #FF8000">/// &lt;summary&gt;<br />
    /// Allows to limit execution time of a Jurassic Script by internally using the<br />
    /// technique of aborting a thread.<br />
    /// &lt;/summary&gt;<br />
    </span><span style="color: #007700">public class </span><span style="color: #0000BB">ScriptTimeoutHelper<br />
    </span><span style="color: #007700">{<br />
        private </span><span style="color: #0000BB">HandlerState currentState</span><span style="color: #007700">;<br />
<br />
        public </span><span style="color: #0000BB">ScriptTimeoutHelper</span><span style="color: #007700">()<br />
        {<br />
        }<br />
<br />
        </span><span style="color: #FF8000">/// &lt;summary&gt;<br />
        /// Runs the specified &lt;see cref="Action"/&gt; in the current thread,<br />
        /// applying the given timeout.<br />
        /// When the handler times out, a &lt;see cref="ThreadAbortException"/&gt; is<br />
        /// raised in the current thread to break. However, this is managed<br />
        /// internally so it does not affect the caller of this method (i.e. it is<br />
        /// ensured that a &lt;see cref="ThreadAbortException"/&gt; does not flow through<br />
        /// this method or raised after this method returns).<br />
        /// &lt;/summary&gt;<br />
        /// &lt;exception cref="TimeoutException"&gt;Thrown when the handler times <br />
        /// out.&lt;/exception&gt;<br />
        /// &lt;param name="handler"&gt;&lt;/param&gt;<br />
        /// &lt;param name="timeout"&gt;&lt;/param&gt;<br />
        </span><span style="color: #007700">public </span><span style="color: #0000BB">void RunWithTimeout</span><span style="color: #007700">(</span><span style="color: #0000BB">Action handler</span><span style="color: #007700">, </span><span style="color: #0000BB">int timeout</span><span style="color: #007700">)<br />
        {<br />
            if (</span><span style="color: #0000BB">currentState </span><span style="color: #007700">!= </span><span style="color: #0000BB">null</span><span style="color: #007700">)<br />
                throw new </span><span style="color: #0000BB">InvalidOperationException</span><span style="color: #007700">(<br />
                    $</span><span style="color: #DD0000">"Cannot recursively call {nameof(RunWithTimeout)}."</span><span style="color: #007700">);<br />
            if (</span><span style="color: #0000BB">handler </span><span style="color: #007700">== </span><span style="color: #0000BB">null</span><span style="color: #007700">)<br />
                throw new </span><span style="color: #0000BB">ArgumentException</span><span style="color: #007700">(</span><span style="color: #0000BB">nameof</span><span style="color: #007700">(</span><span style="color: #0000BB">handler</span><span style="color: #007700">));<br />
<br />
            </span><span style="color: #FF8000">// Throw the TimeoutException immediately when the timeout is 0.<br />
            </span><span style="color: #007700">if (</span><span style="color: #0000BB">timeout </span><span style="color: #007700">== </span><span style="color: #0000BB">0</span><span style="color: #007700">)<br />
                throw new </span><span style="color: #0000BB">TimeoutException</span><span style="color: #007700">();<br />
<br />
            </span><span style="color: #0000BB">ExceptionDispatchInfo caughtException </span><span style="color: #007700">= </span><span style="color: #0000BB">null</span><span style="color: #007700">;<br />
<br />
            </span><span style="color: #0000BB">using </span><span style="color: #007700">(var </span><span style="color: #0000BB">state </span><span style="color: #007700">= </span><span style="color: #0000BB">currentState </span><span style="color: #007700">=<br />
                new </span><span style="color: #0000BB">HandlerState</span><span style="color: #007700">(</span><span style="color: #0000BB">Thread</span><span style="color: #007700">.</span><span style="color: #0000BB">CurrentThread</span><span style="color: #007700">))<br />
            {<br />
                </span><span style="color: #FF8000">/* Start a monitoring task that may abort the current thread after<br />
                 * the specified time limit.<br />
                 * Note that the task will start immediately. Therefore we need to<br />
                 * ensure the task does not abort the thread until we entered the<br />
                 * try clause; otherwise the ThreadAbortException might fly through<br />
                 * the caller of this method. To ensure this, the monitoring task<br />
                 * waits until we release the semaphore the first time before<br />
                 * actually waiting for the specified time.<br />
                */<br />
                </span><span style="color: #0000BB">using </span><span style="color: #007700">(var </span><span style="color: #0000BB">monitoringTask </span><span style="color: #007700">= </span><span style="color: #0000BB">Task</span><span style="color: #007700">.</span><span style="color: #0000BB">Run</span><span style="color: #007700">(</span><span style="color: #0000BB">async </span><span style="color: #007700">() =&gt;<br />
                    </span><span style="color: #0000BB">await RunMonitoringTask</span><span style="color: #007700">(</span><span style="color: #0000BB">state</span><span style="color: #007700">, </span><span style="color: #0000BB">timeout</span><span style="color: #007700">)))<br />
                {<br />
                    try<br />
                    {<br />
                        </span><span style="color: #0000BB">bool waitForAbortException</span><span style="color: #007700">;<br />
                        try<br />
                        {<br />
                            </span><span style="color: #FF8000">// Allow the monitoring task to begin by releasing the<br />
                            // semaphore the first time.<br />
                            // Do this in a finally block to ensure if this thread<br />
                            // is aborted by other code, the semaphore is still<br />
                            // released.<br />
                            </span><span style="color: #007700">try { }<br />
                            finally<br />
                            {<br />
                                </span><span style="color: #0000BB">state</span><span style="color: #007700">.</span><span style="color: #0000BB">WaitSemaphore</span><span style="color: #007700">.</span><span style="color: #0000BB">Release</span><span style="color: #007700">();<br />
                            }<br />
<br />
                            </span><span style="color: #FF8000">// Execute the handler.<br />
                            </span><span style="color: #0000BB">handler</span><span style="color: #007700">();<br />
                        }<br />
                        catch (</span><span style="color: #0000BB">Exception ex</span><span style="color: #007700">) </span><span style="color: #0000BB">when </span><span style="color: #007700">(!(</span><span style="color: #0000BB">ex is ThreadAbortException</span><span style="color: #007700">))<br />
                        {<br />
                            </span><span style="color: #FF8000">/* Need to catch all exceptions (except our own<br />
                             * ThreadAbortException) because we may wait for a<br />
                             * ThreadAbortException to be thrown which is not<br />
                             * possible in a finally handler.<br />
                             */<br />
                            </span><span style="color: #0000BB">caughtException </span><span style="color: #007700">= </span><span style="color: #0000BB">ExceptionDispatchInfo</span><span style="color: #007700">.</span><span style="color: #0000BB">Capture</span><span style="color: #007700">(</span><span style="color: #0000BB">ex</span><span style="color: #007700">);<br />
                        }<br />
                        finally<br />
                        {<br />
                            </span><span style="color: #FF8000">/* Indicate that the handler is completed, and check<br />
                             * if we need to wait for the ThreadAbortException.<br />
                             * This is done in a finally handler to ensure when<br />
                             * other code wants to abort this thread, the thread<br />
                             * actually will abort as expected but we still can<br />
                             * notify the monitoring task that we already returned.<br />
                             */<br />
                            </span><span style="color: #0000BB">lock </span><span style="color: #007700">(</span><span style="color: #0000BB">state</span><span style="color: #007700">)<br />
                            {<br />
                                </span><span style="color: #0000BB">state</span><span style="color: #007700">.</span><span style="color: #0000BB">IsExited </span><span style="color: #007700">= </span><span style="color: #0000BB">true</span><span style="color: #007700">;<br />
                                </span><span style="color: #0000BB">waitForAbortException </span><span style="color: #007700">=<br />
                                    </span><span style="color: #0000BB">state</span><span style="color: #007700">.</span><span style="color: #0000BB">AbortState </span><span style="color: #007700">== </span><span style="color: #0000BB">AbortState</span><span style="color: #007700">.</span><span style="color: #0000BB">IsAborting</span><span style="color: #007700">;<br />
<br />
                                if (</span><span style="color: #0000BB">state</span><span style="color: #007700">.</span><span style="color: #0000BB">AbortState </span><span style="color: #007700">== </span><span style="color: #0000BB">AbortState</span><span style="color: #007700">.</span><span style="color: #0000BB">None</span><span style="color: #007700">)<br />
                                {<br />
                                    </span><span style="color: #FF8000">// If the monitoring task did not do anything<br />
                                    // yet, allow it to complete immediately.<br />
                                    </span><span style="color: #0000BB">state</span><span style="color: #007700">.</span><span style="color: #0000BB">WaitSemaphore</span><span style="color: #007700">.</span><span style="color: #0000BB">Release</span><span style="color: #007700">();<br />
                                }<br />
                            }<br />
                        }<br />
<br />
                        if (</span><span style="color: #0000BB">waitForAbortException</span><span style="color: #007700">)<br />
                        {<br />
                            </span><span style="color: #FF8000">/* The monitoring task indicated that it will abort our<br />
                             * thread (but the ThreadAbortException did not yet<br />
                             * occur), so we need to wait for the<br />
                             * ThreadAbortException.<br />
                             * This wait is needed because otherwise we may return<br />
                             * too early (and in the finally block we wait for the<br />
                             * monitoring task, causing a deadlock).<br />
                             */<br />
                            </span><span style="color: #0000BB">Thread</span><span style="color: #007700">.</span><span style="color: #0000BB">Sleep</span><span style="color: #007700">(</span><span style="color: #0000BB">Timeout</span><span style="color: #007700">.</span><span style="color: #0000BB">Infinite</span><span style="color: #007700">);<br />
                        }<br />
                    }<br />
                    catch (</span><span style="color: #0000BB">ThreadAbortException ex</span><span style="color: #007700">)<br />
                        </span><span style="color: #0000BB">when </span><span style="color: #007700">(</span><span style="color: #0000BB">ex</span><span style="color: #007700">.</span><span style="color: #0000BB">ExceptionState </span><span style="color: #007700">== </span><span style="color: #0000BB">state</span><span style="color: #007700">)<br />
                    {<br />
                        </span><span style="color: #FF8000">// Reset the abort.<br />
                        </span><span style="color: #0000BB">Thread</span><span style="color: #007700">.</span><span style="color: #0000BB">ResetAbort</span><span style="color: #007700">();<br />
<br />
                        </span><span style="color: #FF8000">// Indicate that the timeout has been exceeded.<br />
                        </span><span style="color: #007700">throw new </span><span style="color: #0000BB">TimeoutException</span><span style="color: #007700">();<br />
                    }<br />
                    finally<br />
                    {<br />
                        </span><span style="color: #FF8000">// Wait for the monitoring task to complete.<br />
                        </span><span style="color: #0000BB">monitoringTask</span><span style="color: #007700">.</span><span style="color: #0000BB">Wait</span><span style="color: #007700">();<br />
                        </span><span style="color: #0000BB">currentState </span><span style="color: #007700">= </span><span style="color: #0000BB">null</span><span style="color: #007700">;<br />
                    }<br />
                }<br />
            }<br />
<br />
            </span><span style="color: #FF8000">// Check if we need to rethrow a caught exception (preserving the<br />
            // original stacktrace).<br />
            </span><span style="color: #007700">if (</span><span style="color: #0000BB">caughtException </span><span style="color: #007700">!= </span><span style="color: #0000BB">null</span><span style="color: #007700">)<br />
                </span><span style="color: #0000BB">caughtException</span><span style="color: #007700">.Throw();<br />
        }<br />
<br />
        private </span><span style="color: #0000BB">async Task RunMonitoringTask</span><span style="color: #007700">(</span><span style="color: #0000BB">HandlerState state</span><span style="color: #007700">, </span><span style="color: #0000BB">int timeout</span><span style="color: #007700">)<br />
        {<br />
            </span><span style="color: #FF8000">// Wait until the handler thread entered the try-block.<br />
            // Use a synchronous wait because we expect this to be a very short<br />
            // period of time.<br />
            </span><span style="color: #0000BB">state</span><span style="color: #007700">.</span><span style="color: #0000BB">WaitSemaphore</span><span style="color: #007700">.</span><span style="color: #0000BB">Wait</span><span style="color: #007700">();<br />
<br />
            </span><span style="color: #FF8000">// Now asynchronously wait until the specified time has passed or the<br />
            // semaphore has been released. In the latter case there is no need to<br />
            // call AbortExecution().<br />
            </span><span style="color: #0000BB">bool completed </span><span style="color: #007700">= </span><span style="color: #0000BB">await state</span><span style="color: #007700">.</span><span style="color: #0000BB">WaitSemaphore</span><span style="color: #007700">.</span><span style="color: #0000BB">WaitAsync</span><span style="color: #007700">(</span><span style="color: #0000BB">timeout</span><span style="color: #007700">);<br />
<br />
            </span><span style="color: #FF8000">// Abort the handler thread.<br />
            </span><span style="color: #007700">if (!</span><span style="color: #0000BB">completed</span><span style="color: #007700">)<br />
                </span><span style="color: #0000BB">AbortExecution</span><span style="color: #007700">(</span><span style="color: #0000BB">state</span><span style="color: #007700">);<br />
        }<br />
<br />
        private </span><span style="color: #0000BB">void AbortExecution</span><span style="color: #007700">(</span><span style="color: #0000BB">HandlerState state</span><span style="color: #007700">)<br />
        {<br />
            </span><span style="color: #0000BB">bool canAbort</span><span style="color: #007700">;<br />
            </span><span style="color: #0000BB">lock </span><span style="color: #007700">(</span><span style="color: #0000BB">state</span><span style="color: #007700">)<br />
            {<br />
                if (</span><span style="color: #0000BB">state</span><span style="color: #007700">.</span><span style="color: #0000BB">IsExited</span><span style="color: #007700">)<br />
                {<br />
                    </span><span style="color: #FF8000">// The handler has already exited.<br />
                    </span><span style="color: #007700">return;<br />
                }<br />
<br />
                </span><span style="color: #FF8000">// Check if we can call Thread.Abort() or if the handler thread is<br />
                // currently in a critical section and needs to abort himself when<br />
                // leaving the critical section.<br />
                </span><span style="color: #0000BB">canAbort </span><span style="color: #007700">= !</span><span style="color: #0000BB">state</span><span style="color: #007700">.</span><span style="color: #0000BB">IsCriticalSection</span><span style="color: #007700">;<br />
                </span><span style="color: #0000BB">state</span><span style="color: #007700">.</span><span style="color: #0000BB">AbortState </span><span style="color: #007700">= </span><span style="color: #0000BB">canAbort </span><span style="color: #007700">? </span><span style="color: #0000BB">AbortState</span><span style="color: #007700">.</span><span style="color: #0000BB">IsAborting<br />
                    </span><span style="color: #007700">: </span><span style="color: #0000BB">AbortState</span><span style="color: #007700">.</span><span style="color: #0000BB">ShouldAbort</span><span style="color: #007700">;<br />
            }<br />
            if (</span><span style="color: #0000BB">canAbort</span><span style="color: #007700">)<br />
            {<br />
                </span><span style="color: #FF8000">/* The handler thread is not in a critical section so we can<br />
                 * directly abort it.<br />
                 * This needs to be done outside of the lock because Abort() could<br />
                 * block if the  thread is currently in a finally handler (and<br />
                 * trying to lock on the state object), which could lead to a<br />
                 * deadlock.<br />
                 */<br />
                </span><span style="color: #0000BB">state</span><span style="color: #007700">.</span><span style="color: #0000BB">HandlerThread</span><span style="color: #007700">.</span><span style="color: #0000BB">Abort</span><span style="color: #007700">(</span><span style="color: #0000BB">state</span><span style="color: #007700">);<br />
            }<br />
        }<br />
<br />
        </span><span style="color: #FF8000">/// &lt;summary&gt;<br />
        /// Notifies this class that the handler thread is entering a critical<br />
        /// section in which aborting the thread could corrupt the system's state.<br />
        /// This means aborting the thread will be deferred until leaving the<br />
        /// critical section.<br />
        /// Note that you must call &lt;see cref="ExitCriticalSection"/&gt; in a<br />
        /// &lt;c&gt;finally&lt;/c&gt; block once the thread left the critical section.<br />
        /// &lt;/summary&gt;<br />
        </span><span style="color: #007700">public </span><span style="color: #0000BB">void EnterCriticalSection</span><span style="color: #007700">()<br />
        {<br />
            if (</span><span style="color: #0000BB">currentState </span><span style="color: #007700">== </span><span style="color: #0000BB">null</span><span style="color: #007700">)<br />
                throw new </span><span style="color: #0000BB">InvalidOperationException</span><span style="color: #007700">();<br />
<br />
            </span><span style="color: #0000BB">bool waitForAbortException</span><span style="color: #007700">;<br />
            </span><span style="color: #0000BB">lock </span><span style="color: #007700">(</span><span style="color: #0000BB">currentState</span><span style="color: #007700">)<br />
            {<br />
                if (</span><span style="color: #0000BB">Thread</span><span style="color: #007700">.</span><span style="color: #0000BB">CurrentThread </span><span style="color: #007700">!= </span><span style="color: #0000BB">currentState</span><span style="color: #007700">.</span><span style="color: #0000BB">HandlerThread<br />
                    </span><span style="color: #007700">|| </span><span style="color: #0000BB">currentState</span><span style="color: #007700">.</span><span style="color: #0000BB">IsCriticalSection</span><span style="color: #007700">)<br />
                    throw new </span><span style="color: #0000BB">InvalidOperationException</span><span style="color: #007700">();<br />
<br />
                </span><span style="color: #0000BB">currentState</span><span style="color: #007700">.</span><span style="color: #0000BB">IsCriticalSection </span><span style="color: #007700">= </span><span style="color: #0000BB">true</span><span style="color: #007700">;<br />
                </span><span style="color: #0000BB">waitForAbortException </span><span style="color: #007700">=<br />
                    </span><span style="color: #0000BB">currentState</span><span style="color: #007700">.</span><span style="color: #0000BB">AbortState </span><span style="color: #007700">== </span><span style="color: #0000BB">AbortState</span><span style="color: #007700">.</span><span style="color: #0000BB">IsAborting</span><span style="color: #007700">;<br />
            }<br />
            if (</span><span style="color: #0000BB">waitForAbortException</span><span style="color: #007700">)<br />
            {<br />
                </span><span style="color: #FF8000">// The monitoring task indicated that it will abort our thread, so<br />
                // we need to wait for the ThreadAbortException.<br />
                </span><span style="color: #0000BB">Thread</span><span style="color: #007700">.</span><span style="color: #0000BB">Sleep</span><span style="color: #007700">(</span><span style="color: #0000BB">Timeout</span><span style="color: #007700">.</span><span style="color: #0000BB">Infinite</span><span style="color: #007700">);<br />
            }<br />
        }<br />
<br />
        public </span><span style="color: #0000BB">void ExitCriticalSection</span><span style="color: #007700">()<br />
        {<br />
            if (</span><span style="color: #0000BB">currentState </span><span style="color: #007700">== </span><span style="color: #0000BB">null</span><span style="color: #007700">)<br />
                throw new </span><span style="color: #0000BB">InvalidOperationException</span><span style="color: #007700">();<br />
<br />
            </span><span style="color: #0000BB">bool shouldAbort</span><span style="color: #007700">;<br />
            </span><span style="color: #0000BB">lock </span><span style="color: #007700">(</span><span style="color: #0000BB">currentState</span><span style="color: #007700">)<br />
            {<br />
                if (</span><span style="color: #0000BB">Thread</span><span style="color: #007700">.</span><span style="color: #0000BB">CurrentThread </span><span style="color: #007700">!= </span><span style="color: #0000BB">currentState</span><span style="color: #007700">.</span><span style="color: #0000BB">HandlerThread<br />
                    </span><span style="color: #007700">|| !</span><span style="color: #0000BB">currentState</span><span style="color: #007700">.</span><span style="color: #0000BB">IsCriticalSection</span><span style="color: #007700">)<br />
                    throw new </span><span style="color: #0000BB">InvalidOperationException</span><span style="color: #007700">();<br />
<br />
                </span><span style="color: #0000BB">currentState</span><span style="color: #007700">.</span><span style="color: #0000BB">IsCriticalSection </span><span style="color: #007700">= </span><span style="color: #0000BB">false</span><span style="color: #007700">;<br />
                </span><span style="color: #0000BB">shouldAbort </span><span style="color: #007700">= </span><span style="color: #0000BB">currentState</span><span style="color: #007700">.</span><span style="color: #0000BB">AbortState </span><span style="color: #007700">== </span><span style="color: #0000BB">AbortState</span><span style="color: #007700">.</span><span style="color: #0000BB">ShouldAbort</span><span style="color: #007700">;<br />
            }<br />
            if (</span><span style="color: #0000BB">shouldAbort</span><span style="color: #007700">)<br />
            {<br />
                </span><span style="color: #FF8000">// The monitoring task indicated that it wanted to abort our<br />
                // thread while we were in a critical section, so we need to abort<br />
                // ourselves.<br />
                </span><span style="color: #0000BB">Thread</span><span style="color: #007700">.</span><span style="color: #0000BB">CurrentThread</span><span style="color: #007700">.</span><span style="color: #0000BB">Abort</span><span style="color: #007700">(</span><span style="color: #0000BB">currentState</span><span style="color: #007700">);<br />
            }<br />
        }<br />
<br />
        private enum </span><span style="color: #0000BB">AbortState<br />
        </span><span style="color: #007700">{<br />
            </span><span style="color: #FF8000">/// &lt;summary&gt;<br />
            /// Indicates that the monitoring task has not yet done any action.<br />
            /// &lt;/summary&gt;<br />
            </span><span style="color: #0000BB">None </span><span style="color: #007700">= </span><span style="color: #0000BB">0</span><span style="color: #007700">,<br />
<br />
            </span><span style="color: #FF8000">/// &lt;summary&gt;<br />
            /// Indicates that the monitoring task is about to abort the handler<br />
            /// thread.<br />
            /// &lt;/summary&gt;<br />
            </span><span style="color: #0000BB">IsAborting </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">,<br />
<br />
            </span><span style="color: #FF8000">/// &lt;summary&gt;<br />
            /// Indicates that the monitoring task wanted to abort the handler<br />
            /// thread but the handler thread was in a critical section, and needs<br />
            /// to abort itself when leaving the critical section.<br />
            /// &lt;/summary&gt;<br />
            </span><span style="color: #0000BB">ShouldAbort </span><span style="color: #007700">= </span><span style="color: #0000BB">2<br />
        </span><span style="color: #007700">}<br />
<br />
        private class </span><span style="color: #0000BB">HandlerState </span><span style="color: #007700">: </span><span style="color: #0000BB">IDisposable<br />
        </span><span style="color: #007700">{<br />
<br />
            public </span><span style="color: #0000BB">Thread HandlerThread </span><span style="color: #007700">{ </span><span style="color: #0000BB">get</span><span style="color: #007700">; }<br />
<br />
            public </span><span style="color: #0000BB">SemaphoreSlim WaitSemaphore </span><span style="color: #007700">{ </span><span style="color: #0000BB">get</span><span style="color: #007700">; } = new </span><span style="color: #0000BB">SemaphoreSlim</span><span style="color: #007700">(</span><span style="color: #0000BB">0</span><span style="color: #007700">);<br />
<br />
            public </span><span style="color: #0000BB">bool IsCriticalSection </span><span style="color: #007700">{ </span><span style="color: #0000BB">get</span><span style="color: #007700">; </span><span style="color: #0000BB">set</span><span style="color: #007700">; }<br />
<br />
            </span><span style="color: #FF8000">/// &lt;summary&gt;<br />
            /// Indicates if the handler is already completed (so there's no need<br />
            /// to abort the thread).<br />
            /// This flag is set by the handler thread.<br />
            /// &lt;/summary&gt;<br />
            </span><span style="color: #007700">public </span><span style="color: #0000BB">bool IsExited </span><span style="color: #007700">{ </span><span style="color: #0000BB">get</span><span style="color: #007700">; </span><span style="color: #0000BB">set</span><span style="color: #007700">; }<br />
<br />
            </span><span style="color: #FF8000">/// &lt;summary&gt;<br />
            /// Indicates that the wait task wanted to abort the handler thread but<br />
            /// the handler thread was in a critical section, and needs to abort<br />
            /// itself when leaving the critical section.<br />
            /// This flag is set by the wait task.<br />
            /// &lt;/summary&gt;<br />
            </span><span style="color: #007700">public </span><span style="color: #0000BB">AbortState AbortState </span><span style="color: #007700">{ </span><span style="color: #0000BB">get</span><span style="color: #007700">; </span><span style="color: #0000BB">set</span><span style="color: #007700">; }<br />
<br />
<br />
            public </span><span style="color: #0000BB">HandlerState</span><span style="color: #007700">(</span><span style="color: #0000BB">Thread handlerThread</span><span style="color: #007700">)<br />
            {<br />
                </span><span style="color: #0000BB">this</span><span style="color: #007700">.</span><span style="color: #0000BB">HandlerThread </span><span style="color: #007700">= </span><span style="color: #0000BB">handlerThread</span><span style="color: #007700">;<br />
            }<br />
<br />
            ~</span><span style="color: #0000BB">HandlerState</span><span style="color: #007700">()<br />
            {<br />
                </span><span style="color: #0000BB">Dispose</span><span style="color: #007700">(</span><span style="color: #0000BB">false</span><span style="color: #007700">);<br />
            }<br />
<br />
            public </span><span style="color: #0000BB">void Dispose</span><span style="color: #007700">()<br />
            {<br />
                </span><span style="color: #0000BB">Dispose</span><span style="color: #007700">(</span><span style="color: #0000BB">true</span><span style="color: #007700">);<br />
                </span><span style="color: #0000BB">GC</span><span style="color: #007700">.</span><span style="color: #0000BB">SuppressFinalize</span><span style="color: #007700">(</span><span style="color: #0000BB">this</span><span style="color: #007700">);<br />
            }<br />
<br />
            protected </span><span style="color: #0000BB">void Dispose</span><span style="color: #007700">(</span><span style="color: #0000BB">bool disposing</span><span style="color: #007700">)<br />
            {<br />
                if (</span><span style="color: #0000BB">disposing</span><span style="color: #007700">)<br />
                {<br />
                    </span><span style="color: #0000BB">WaitSemaphore</span><span style="color: #007700">.</span><span style="color: #0000BB">Dispose</span><span style="color: #007700">();<br />
                }<br />
            }<br />
        }<br />
    }<br />
} </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
<br />
原来执行javascpript的方式如下：<br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_qglg0IL8pJo6')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_qglg0IL8pJo6);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_qglg0IL8pJo6" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #007700">var </span><span style="color: #0000BB">engine </span><span style="color: #007700">= new </span><span style="color: #0000BB">ScriptEngine</span><span style="color: #007700">();<br />
var </span><span style="color: #0000BB">compiledScript </span><span style="color: #007700">= </span><span style="color: #0000BB">engine</span><span style="color: #007700">.</span><span style="color: #0000BB">Compile</span><span style="color: #007700">(new </span><span style="color: #0000BB">StringScriptSource</span><span style="color: #007700">(<br />
    </span><span style="color: #DD0000">"while (true) ;"</span><span style="color: #007700">));<br />
</span><span style="color: #0000BB">compiledScript</span><span style="color: #007700">.</span><span style="color: #0000BB">Execute</span><span style="color: #007700">(); </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
<br />
<h2>改进后新的执行javascpript的方式如下：</h2><br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_nUgRB74OzmZL')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_nUgRB74OzmZL);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_nUgRB74OzmZL" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #007700">var </span><span style="color: #0000BB">timeoutHelper </span><span style="color: #007700">= new </span><span style="color: #0000BB">ScriptTimeoutHelper</span><span style="color: #007700">();<br />
var </span><span style="color: #0000BB">engine </span><span style="color: #007700">= new </span><span style="color: #0000BB">ScriptEngine</span><span style="color: #007700">();<br />
var </span><span style="color: #0000BB">compiledScript </span><span style="color: #007700">= </span><span style="color: #0000BB">engine</span><span style="color: #007700">.</span><span style="color: #0000BB">Compile</span><span style="color: #007700">(new </span><span style="color: #0000BB">StringScriptSource</span><span style="color: #007700">(<br />
    </span><span style="color: #DD0000">"while (true) ;"</span><span style="color: #007700">));<br />
try{<br />
</span><span style="color: #0000BB">timeoutHelper</span><span style="color: #007700">.</span><span style="color: #0000BB">RunWithTimeout</span><span style="color: #007700">(() =&gt; </span><span style="color: #0000BB">compiledScript</span><span style="color: #007700">.</span><span style="color: #0000BB">Execute</span><span style="color: #007700">(), </span><span style="color: #0000BB">1000</span><span style="color: #007700">);<br />
}<br />
catch(</span><span style="color: #0000BB">TimeoutException ex</span><span style="color: #007700">){<br />
</span><span style="color: #FF8000">//这里表示执行超时<br />
</span><span style="color: #007700">}<br />
 </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
<br />
<h2>注意事项：</h2><br />
<div class="txt_main">我们使用useScriptEngine.Compile()首先编译脚本，然后将超时仅应用于实际执行脚本。<br />
上面的调用代码设置的超时时间是1秒，如果JavaScript未在1秒钟内完成，我们将捕获到TimeoutException异常。<br />
<br />
<br />
<strong>注：在发生TimeoutException以后，我们不应该继续使用ScriptEngine及其关联的对象实例，因为它们可能处于不一致/不可用状态。而是创建一个新的ScriptEngine实例以运行更多脚本文件。</strong><br />
<br />
</div>]]></content:encoded>
<link>https://www.rickw.cn/blogview/283</link>
<dc:subject>C# .Net编程</dc:subject>
<dc:creator>rick</dc:creator>
<dc:date>2023-12-01 23:12:13</dc:date>
</item>
		
<item rdf:about="https://www.rickw.cn/blogview/279">
<title><![CDATA[介绍一个C#的javascpript引擎 Jurassic]]></title>
	
<description><![CDATA[这是一个纯.Net实现的javascpript引擎，目前支持ECMAScript&nbsp;3&nbsp;和&nbsp;ECMAScript&nbsp;5&nbsp;包括&nbsp;ES5&nbsp;strict&nbsp;模式。<br />
ECMAScript&nbsp;6的支持还在开发中，已经支持了es6的大部分特性。<br />
<br />
性能好：它将JavaScript编译为.NET字节码（CIL），而非解释执行。这样使得它的运行性能更好；<br />
<br />]]></description>
<content:encoded><![CDATA[这是一个纯.Net实现的javascpript引擎，目前支持ECMAScript&nbsp;3&nbsp;和&nbsp;ECMAScript&nbsp;5&nbsp;包括&nbsp;ES5&nbsp;strict&nbsp;模式。<br />
ECMAScript&nbsp;6的支持还在开发中，已经支持了es6的大部分特性。<br />
<br />
性能好：它将JavaScript编译为.NET字节码（CIL），而非解释执行。这样使得它的运行性能更好；<br />
<br />
纯.Net开发：纯.Net开发，不依赖任何第三方库，只有单个dll文件，可以完全集成到.Net框架中，可以在任何支持.Net平台执行；<br />
<br />
使用：<br />
1，可以直接用&nbsp;NuGet&nbsp;获取&nbsp;Jurassic。<br />
<div class="txt_main">using&nbsp;Jurassic;</div><br />
简单的执行js字符串<br />
<div class="txt_main">var&nbsp;engine&nbsp;=&nbsp;new&nbsp;Jurassic.ScriptEngine();<br />
&nbsp;engine.Evaluate("function&nbsp;main(a,b){return&nbsp;a+b;}");<br />
var&nbsp;addResult=&nbsp;engine.CallGlobalFunction("main",&nbsp;5,&nbsp;6);//结果11<br />
</div><br />
<br />
2，.Net&nbsp;和&nbsp;javascpript&nbsp;之间交互。<br />
<div class="txt_main"><strong>暴露net的class给js</strong><br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_nX3CBaGZcHds')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_nX3CBaGZcHds);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_nX3CBaGZcHds" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #0000BB"><br />
using Jurassic</span><span style="color: #007700">;<br />
</span><span style="color: #0000BB">using Jurassic</span><span style="color: #007700">.</span><span style="color: #0000BB">Library</span><span style="color: #007700">;<br />
<br />
public class </span><span style="color: #0000BB">AppInfo </span><span style="color: #007700">: </span><span style="color: #0000BB">ObjectInstance<br />
</span><span style="color: #007700">{<br />
    public </span><span style="color: #0000BB">AppInfo</span><span style="color: #007700">(</span><span style="color: #0000BB">ScriptEngine engine</span><span style="color: #007700">)<br />
        : </span><span style="color: #0000BB">base</span><span style="color: #007700">(</span><span style="color: #0000BB">engine</span><span style="color: #007700">)<br />
    {<br />
        </span><span style="color: #FF8000">// 重写name属性<br />
        </span><span style="color: #0000BB">this</span><span style="color: #007700">[</span><span style="color: #DD0000">"name"</span><span style="color: #007700">] = </span><span style="color: #DD0000">"Test Application"</span><span style="color: #007700">;<br />
<br />
        </span><span style="color: #FF8000">// 只读属性<br />
        </span><span style="color: #0000BB">this</span><span style="color: #007700">.</span><span style="color: #0000BB">DefineProperty</span><span style="color: #007700">(</span><span style="color: #DD0000">"version"</span><span style="color: #007700">, new </span><span style="color: #0000BB">PropertyDescriptor</span><span style="color: #007700">(</span><span style="color: #0000BB">5</span><span style="color: #007700">, </span><span style="color: #0000BB">PropertyAttributes</span><span style="color: #007700">.</span><span style="color: #0000BB">Sealed</span><span style="color: #007700">), </span><span style="color: #0000BB">true</span><span style="color: #007700">);<br />
    }<br />
}<br />
 <br />
</span><span style="color: #0000BB">engine</span><span style="color: #007700">.</span><span style="color: #0000BB">SetGlobalValue</span><span style="color: #007700">(</span><span style="color: #DD0000">"appInfo"</span><span style="color: #007700">, new </span><span style="color: #0000BB">AppInfo</span><span style="color: #007700">(</span><span style="color: #0000BB">engine</span><span style="color: #007700">));<br />
</span><span style="color: #0000BB">Console</span><span style="color: #007700">.</span><span style="color: #0000BB">WriteLine</span><span style="color: #007700">(</span><span style="color: #0000BB">engine</span><span style="color: #007700">.</span><span style="color: #0000BB">Evaluate</span><span style="color: #007700">&lt;</span><span style="color: #0000BB">string</span><span style="color: #007700">&gt;(</span><span style="color: #DD0000">"appInfo.name + ' ' + appInfo.version"</span><span style="color: #007700">)); </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
<br />
<strong>暴露net的class的静态方法</strong><br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_CXXqhA0tqxqf')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_CXXqhA0tqxqf);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_CXXqhA0tqxqf" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #0000BB"><br />
using Jurassic</span><span style="color: #007700">;<br />
</span><span style="color: #0000BB">using Jurassic</span><span style="color: #007700">.</span><span style="color: #0000BB">Library</span><span style="color: #007700">;<br />
<br />
public class </span><span style="color: #0000BB">Math2 </span><span style="color: #007700">: </span><span style="color: #0000BB">ObjectInstance<br />
</span><span style="color: #007700">{<br />
    public </span><span style="color: #0000BB">Math2</span><span style="color: #007700">(</span><span style="color: #0000BB">ScriptEngine engine</span><span style="color: #007700">)<br />
        : </span><span style="color: #0000BB">base</span><span style="color: #007700">(</span><span style="color: #0000BB">engine</span><span style="color: #007700">)<br />
    {<br />
        </span><span style="color: #0000BB">this</span><span style="color: #007700">.</span><span style="color: #0000BB">PopulateFunctions</span><span style="color: #007700">();<br />
    }<br />
<br />
    [</span><span style="color: #0000BB">JSFunction</span><span style="color: #007700">(</span><span style="color: #0000BB">Name </span><span style="color: #007700">= </span><span style="color: #DD0000">"log10"</span><span style="color: #007700">)]<br />
    public static </span><span style="color: #0000BB">double Log10</span><span style="color: #007700">(</span><span style="color: #0000BB">double num</span><span style="color: #007700">)<br />
    {<br />
        return </span><span style="color: #0000BB">Math</span><span style="color: #007700">.</span><span style="color: #0000BB">Log10</span><span style="color: #007700">(</span><span style="color: #0000BB">num</span><span style="color: #007700">);<br />
    }<br />
}<br />
 <br />
</span><span style="color: #0000BB">engine</span><span style="color: #007700">.</span><span style="color: #0000BB">SetGlobalValue</span><span style="color: #007700">(</span><span style="color: #DD0000">"math2"</span><span style="color: #007700">, new </span><span style="color: #0000BB">Math2</span><span style="color: #007700">(</span><span style="color: #0000BB">engine</span><span style="color: #007700">));<br />
</span><span style="color: #0000BB">engine</span><span style="color: #007700">.</span><span style="color: #0000BB">Evaluate</span><span style="color: #007700">&lt;</span><span style="color: #0000BB">double</span><span style="color: #007700">&gt;(</span><span style="color: #DD0000">"math2.log10(1000)"</span><span style="color: #007700">); </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
<br />
<strong>暴露net的类实例</strong><br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_a5aVo7wVHFSU')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_a5aVo7wVHFSU);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_a5aVo7wVHFSU" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #0000BB"><br />
using Jurassic</span><span style="color: #007700">;<br />
</span><span style="color: #0000BB">using Jurassic</span><span style="color: #007700">.</span><span style="color: #0000BB">Library</span><span style="color: #007700">;<br />
<br />
public class </span><span style="color: #0000BB">RandomConstructor </span><span style="color: #007700">: </span><span style="color: #0000BB">ClrFunction<br />
</span><span style="color: #007700">{<br />
    public </span><span style="color: #0000BB">RandomConstructor</span><span style="color: #007700">(</span><span style="color: #0000BB">ScriptEngine engine</span><span style="color: #007700">)<br />
        : </span><span style="color: #0000BB">base</span><span style="color: #007700">(</span><span style="color: #0000BB">engine</span><span style="color: #007700">.Function.</span><span style="color: #0000BB">InstancePrototype</span><span style="color: #007700">, </span><span style="color: #DD0000">"Random"</span><span style="color: #007700">, new </span><span style="color: #0000BB">RandomInstance</span><span style="color: #007700">(</span><span style="color: #0000BB">engine</span><span style="color: #007700">.</span><span style="color: #0000BB">Object</span><span style="color: #007700">.</span><span style="color: #0000BB">InstancePrototype</span><span style="color: #007700">))<br />
    {<br />
    }<br />
<br />
    [</span><span style="color: #0000BB">JSConstructorFunction</span><span style="color: #007700">]<br />
    public </span><span style="color: #0000BB">RandomInstance Construct</span><span style="color: #007700">(</span><span style="color: #0000BB">int seed</span><span style="color: #007700">)<br />
    {<br />
        return new </span><span style="color: #0000BB">RandomInstance</span><span style="color: #007700">(</span><span style="color: #0000BB">this</span><span style="color: #007700">.</span><span style="color: #0000BB">InstancePrototype</span><span style="color: #007700">, </span><span style="color: #0000BB">seed</span><span style="color: #007700">);<br />
    }<br />
}<br />
<br />
public class </span><span style="color: #0000BB">RandomInstance </span><span style="color: #007700">: </span><span style="color: #0000BB">ObjectInstance<br />
</span><span style="color: #007700">{<br />
    private </span><span style="color: #0000BB">Random random</span><span style="color: #007700">;<br />
<br />
    public </span><span style="color: #0000BB">RandomInstance</span><span style="color: #007700">(</span><span style="color: #0000BB">ObjectInstance prototype</span><span style="color: #007700">)<br />
        : </span><span style="color: #0000BB">base</span><span style="color: #007700">(</span><span style="color: #0000BB">prototype</span><span style="color: #007700">)<br />
    {<br />
        </span><span style="color: #0000BB">this</span><span style="color: #007700">.</span><span style="color: #0000BB">PopulateFunctions</span><span style="color: #007700">();<br />
        </span><span style="color: #0000BB">this</span><span style="color: #007700">.</span><span style="color: #0000BB">random </span><span style="color: #007700">= new </span><span style="color: #0000BB">Random</span><span style="color: #007700">(</span><span style="color: #0000BB">0</span><span style="color: #007700">);<br />
    }<br />
<br />
    public </span><span style="color: #0000BB">RandomInstance</span><span style="color: #007700">(</span><span style="color: #0000BB">ObjectInstance prototype</span><span style="color: #007700">, </span><span style="color: #0000BB">int seed</span><span style="color: #007700">)<br />
        : </span><span style="color: #0000BB">base</span><span style="color: #007700">(</span><span style="color: #0000BB">prototype</span><span style="color: #007700">)<br />
    {<br />
        </span><span style="color: #0000BB">this</span><span style="color: #007700">.</span><span style="color: #0000BB">random </span><span style="color: #007700">= new </span><span style="color: #0000BB">Random</span><span style="color: #007700">(</span><span style="color: #0000BB">seed</span><span style="color: #007700">);<br />
    }<br />
<br />
    [</span><span style="color: #0000BB">JSFunction</span><span style="color: #007700">(</span><span style="color: #0000BB">Name </span><span style="color: #007700">= </span><span style="color: #DD0000">"nextDouble"</span><span style="color: #007700">)]<br />
    public </span><span style="color: #0000BB">double NextDouble</span><span style="color: #007700">()<br />
    {<br />
        return </span><span style="color: #0000BB">this</span><span style="color: #007700">.</span><span style="color: #0000BB">random</span><span style="color: #007700">.</span><span style="color: #0000BB">NextDouble</span><span style="color: #007700">();<br />
    }<br />
}<br />
 <br />
 <br />
</span><span style="color: #0000BB">engine</span><span style="color: #007700">.</span><span style="color: #0000BB">SetGlobalValue</span><span style="color: #007700">(</span><span style="color: #DD0000">"Random"</span><span style="color: #007700">, new </span><span style="color: #0000BB">RandomConstructor</span><span style="color: #007700">(</span><span style="color: #0000BB">engine</span><span style="color: #007700">));<br />
</span><span style="color: #0000BB">engine</span><span style="color: #007700">.</span><span style="color: #0000BB">Evaluate</span><span style="color: #007700">&lt;</span><span style="color: #0000BB">double</span><span style="color: #007700">&gt;(</span><span style="color: #DD0000">"var rand = new Random(1000); rand.nextDouble()"</span><span style="color: #007700">); </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
</div>]]></content:encoded>
<link>https://www.rickw.cn/blogview/279</link>
<dc:subject>C# .Net编程</dc:subject>
<dc:creator>rick</dc:creator>
<dc:date>2023-11-30 14:25:34</dc:date>
</item>
		
<item rdf:about="https://www.rickw.cn/blogview/277">
<title><![CDATA[C#等效于php的password_verify 和 password_hash 功能的函数实现]]></title>
	
<description><![CDATA[<div class="txt_main">C#中能够等价于&nbsp;php&nbsp;password_verify&nbsp;和&nbsp;password_hash&nbsp;功能的实现方法。<br />
有时候可能会需要在C#程序中来验证&nbsp;php&nbsp;生成的哈希密码。实现php系统和C#系统的密码互通。<br />
例如：将php系统迁移到&nbsp;.NetCore的系统。<br />
或者混合使用php系统和.NetCore系统。</div><br />
<br />]]></description>
<content:encoded><![CDATA[<div class="txt_main">C#中能够等价于&nbsp;php&nbsp;password_verify&nbsp;和&nbsp;password_hash&nbsp;功能的实现方法。<br />
有时候可能会需要在C#程序中来验证&nbsp;php&nbsp;生成的哈希密码。实现php系统和C#系统的密码互通。<br />
例如：将php系统迁移到&nbsp;.NetCore的系统。<br />
或者混合使用php系统和.NetCore系统。</div><br />
<br />
<h2>一种保底的实现，间接方式</h2><br />
<div class="txt_main">使用php开发一个api接口，公开给C#调用。</div><br />
<br />
<h2>直接C#实现的方式</h2><br />
<div class="txt_main">php的&nbsp;password_hash&nbsp;使用的是Blowfish加密算法。我们避免重复造轮子，可以利用现成的类库【CryptSharp】。<br />
<strong>C#中实现的验证密码代码如下：</strong><br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_OHmmQWpHcmmU')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_OHmmQWpHcmmU);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_OHmmQWpHcmmU" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #0000BB">using CryptSharp</span><span style="color: #007700">;<br />
</span><span style="color: #FF8000">//等价于PHP的 password_verify 函数<br />
// 验证密码是正确<br />
// inputPassword 用户输入的密码<br />
// hashcryptedPassword PHP的password_hash哈希加密的密码<br />
//<br />
</span><span style="color: #0000BB">bool isOK </span><span style="color: #007700">= </span><span style="color: #0000BB">Crypter</span><span style="color: #007700">.</span><span style="color: #0000BB">CheckPassword</span><span style="color: #007700">(</span><span style="color: #0000BB">inputPassword</span><span style="color: #007700">, </span><span style="color: #0000BB">hashcryptedPassword</span><span style="color: #007700">);<br />
 </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
<br />
<strong>当然我们也可以在C#中实现PHP&nbsp;password_hash&nbsp;等效的加密功能：</strong><br />
<script type="text/javascript">window.attachEvent("onload",function (){AutoSizeDIV('CODE_T4DPJkCZXyEk')})</script><table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="code_head"><tr><td></td><td align="right"><a href="javascript:CopyText(document.all.CODE_T4DPJkCZXyEk);">[复制到剪贴板] </a></td></tr></table><div class="code_main" id="CODE_T4DPJkCZXyEk" style="overflow-y:auto;overflow-x:auto;width: 98%;min-height:40px;max-height:500px;"><pre><code style="color: #000000"><span style="color: #0000BB">using CryptSharp</span><span style="color: #007700">;<br />
</span><span style="color: #FF8000">//等效于PHP的 password_hash 函数<br />
// 和PHP使用相同的加密算法： Blowfish crypt ("BCrypt") <br />
//<br />
</span><span style="color: #0000BB">string hashcryptedPassword </span><span style="color: #007700">= </span><span style="color: #0000BB">Crypter</span><span style="color: #007700">.</span><span style="color: #0000BB">Blowfish</span><span style="color: #007700">.</span><span style="color: #0000BB">Crypt</span><span style="color: #007700">(</span><span style="color: #0000BB">password</span><span style="color: #007700">);<br />
 </span><span style="color: #0000BB">?&gt;</span></code></pre></div><br />
</div><br />
<br />
<h2>类库【CryptSharp】下载</h2><br />
<img src="/images/download.gif" align="absmiddle" /><a target="_blank" href="http://dl.rickw.cn/f/20272120-983481994-5d0dbe">C#加密库CryptSharp_2_1_0.zip</a><br />
]]></content:encoded>
<link>https://www.rickw.cn/blogview/277</link>
<dc:subject>C# .Net编程</dc:subject>
<dc:creator>rick</dc:creator>
<dc:date>2023-11-29 11:19:37</dc:date>
</item>
		
</rdf:Seq>
</items>
</channel>
</rdf:RDF>