背景介绍:
开发环境 :VS2010简体中文旗舰版
.net 版本:.net4.0
CPU :双核四线程【Intel】
错误现象 :使用 TPL 编写多核并行代码,发现只并行了其中的一部分(不能并行到底),之后就由一条线程执行到结束。编译时,代码没有问题,运行时,有时候出现运行到一定程度,程序就卡住,不再执行下去,就像死机一样。下面就贴出代码。
C#并行TPL执行不彻底卡住
开发环境 :VS2010简体中文旗舰版
.net 版本:.net4.0
CPU :双核四线程【Intel】
错误现象 :使用 TPL 编写多核并行代码,发现只并行了其中的一部分(不能并行到底),之后就由一条线程执行到结束。编译时,代码没有问题,运行时,有时候出现运行到一定程度,程序就卡住,不再执行下去,就像死机一样。下面就贴出代码。
C#并行TPL执行不彻底卡住
解决方案 »
- 关于statusStrip控件边角样式的问题
- C#窗口程序中,无法执行键盘触发的方法
- 请问C#能否在客户端直接输出数据库中的提示信息!
- winform程序打包 然后安装的时候 ,在程序菜单里会显示 "微软中国" 请问如何修改或者去掉?
- 关于一些算法问题,求助正宗高手!!
- 关于“模版”的问题
- 放分,順便問個問題
- 继承了List然后想override操作符[]
- 数据结构 C#语言版
- 哪位高手能告诉我,c#.net写的程序是不只能在.net虚拟机下运行?能否和vc.net那样有静态编程?还有就是vc++.net能写的程序在那些方面c#.n
- drawstring怎么绘制CM²
- 一个窗体如何修改另一个窗体的宽高
using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;namespace Test
{
class A
{
public String strName;
public A( String str )
{
this.strName = str;
} public void printMessage()
{
System.DateTime dt = System.DateTime.Now; for( int i = 0; i < 50000; i++ )
{
Console.WriteLine( "当前时间 " + String.Format( "{0:yyyy-MM-dd HH::mm::ss::ffff}",dt ) + " " +
" i = " + i + " " + this.strName ); // 注意时间的格式化;
}
}
} class Program
{
static void Main( string[] args )
{
A a1 = new A( "11111" );
A a2 = new A( "22222" );
A a3 = new A( "33333" );
A a4 = new A( "44444" );
System.Threading.ThreadStart del = delegate()
{
try
{
System.Threading.Tasks.Parallel.Invoke(
() => a1.printMessage(),
() => a2.printMessage(),
() => a3.printMessage(),
() => a4.printMessage()
);
}
catch( AggregateException ex )
{
System.Windows.Forms.MessageBox.Show( "出错了!" + "出错原因:" + ex.Message );
}
}; System.Threading.Thread th = new System.Threading.Thread( del );
th.IsBackground = true;
th.Start(); Console.WriteLine( "单击任意按键可结束测试!" );
Console.ReadKey();
}
}
}贴出图片,可以看出并行代码执行OK,且能执行到底。
using System.Collections.Generic;
using System.Linq;
using System.Text;//using System.Core;
using System.Data;
//using System.Data.DataSetExtensions;
using System.Xml;
using System.Xml.Linq;using System.Threading;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.Runtime.InteropServices;namespace SyncThread
{
public class SyncMethod
{
public System.Windows.Forms.RichTextBox txt; // 指定要输出文本的文本框;
static System.Threading.Semaphore sep = new System.Threading.Semaphore(10, 100);
public SyncMethod( System.Windows.Forms.RichTextBox txt )
{
this.txt = txt;
} public void printMessage( String str,int index )
{
System.DateTime dt = System.DateTime.Now; if( null == this.txt )
{
MessageBox.Show( " txt 值为空!" );
return;
} for( int i = 0; i < 5000; i++ )
{
this.txt.AppendText( "当前时间 " + String.Format("{0:yyyy-MM-dd HH::mm::ss}", dt) + " " + str +
" = " + i + " " + index + "\n" ); // 注意时间的格式化;
sep.Release(); // 释放自增减锁;
}
}
}; public class DoWork
{
private SyncMethod st1;
private SyncMethod st2;
private SyncMethod st3;
private SyncMethod st4; public System.Windows.Forms.RichTextBox txt; public DoWork( System.Windows.Forms.RichTextBox txt )
{
this.txt = txt;
this.st1 = new SyncMethod( this.txt );
this.st2 = new SyncMethod( this.txt );
this.st3 = new SyncMethod( this.txt );
this.st4 = new SyncMethod( this.txt );
} public void handle()
{
System.Threading.ThreadStart del = delegate()
{
try
{
System.Threading.Tasks.Parallel.Invoke(
() => this.st1.printMessage( "aaaa",1111 ),
() => this.st2.printMessage( "bbbb",2222 ),
() => this.st3.printMessage( "cccc",3333 ),
() => this.st4.printMessage( "dddd",4444 )
);
}
catch (System.AggregateException)
{
}
catch (System.Exception)
{
// System.Windows.Forms.MessageBox.Show("出现其他错误," + "出错原因:" + e.Message);
}
}; System.Threading.Thread th = new System.Threading.Thread( del );
th.IsBackground = true;
th.Name = "dowork";
th.Start();
} public void doParelWork()
{
try
{
System.Threading.Tasks.Task t1 = new System.Threading.Tasks.Task(() => this.st1.printMessage("aaaa", 1111));
System.Threading.Tasks.Task t2 = new System.Threading.Tasks.Task(() => this.st2.printMessage("bbbb", 2222));
System.Threading.Tasks.Task t3 = new System.Threading.Tasks.Task(() => this.st3.printMessage("cccc", 3333));
System.Threading.Tasks.Task t4 = new System.Threading.Tasks.Task(() => this.st4.printMessage("dddd", 4444)); t1.Start();
t2.Start();
t3.Start();
t4.Start(); System.Threading.Tasks.Task.WaitAll( t1, t2, t3, t4 );
}
catch (System.AggregateException ex)
{
}
catch (System.Exception e)
{
}
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;using SyncThread;namespace TestThread
{
public partial class Form1 : Form
{
private SyncThread.DoWork dw; // 声明类;
private ShowInfo sf; // 声明委托;
//
// 委托;
//
private delegate void ShowInfo( System.Windows.Forms.RichTextBox txt );
private void showInfo( System.Windows.Forms.RichTextBox txt )
{
this.dw.txt = txt;
} private void controlShow()
{
if( this.InvokeRequired ) // 返回值为 true,表示来自 UI 线程;
//if ( true ) // 返回值为 true,表示来自 UI 线程;
{
Object[] value = { this.txtShow };
this.Invoke(this.sf, value);
} this.dw.handle();
//this.dw.doParelWork();
} public Form1()
{
InitializeComponent();
} private void Form1_Load(object sender, EventArgs e)
{
this.dw = new SyncThread.DoWork( this.txtShow ); // 实例化类;
this.sf = new ShowInfo(this.showInfo); // 实例化;
} private void cmdStart_Click( object sender, EventArgs e )
{
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false; // 这句话也可以加在这里,这么搞;
controlShow();
}
}
}执行结果描述如下:
1、执行时,没有一次并行到底,总是:并行了其中一部分(不能并行到底),之后由一条线程执行到结束;
2、有时候程序中途卡住,就像死机了一样,不响应系统的任何操作,但是系统的其他程序可以正常运行;
3、有时候报告错误。
static System.Threading.Semaphore sep = new System.Threading.Semaphore(10, 100);因为我只启动四条线程,所以这句代码应该是:
static System.Threading.Semaphore sep = new System.Threading.Semaphore(1, 4);现在可以并行到底了,但是 CPU de 的使用率 只有 40% ,并不高,以下贴图佐证:
并行贴图展示:
再问:
再次提问:1、为什么 CPU 的使用率只有 40% ,而控制台的使用了可以到达 95%?2、如何提高 CPU 的使用率? 求指点,TKS
你把System.Threading.Semaphore(10, 100);改为System.Threading.Semaphore(1, 4);还是勿用Semaphore。
我就不相信你那个sep.Release(); 4次循环后不会报错。但或许你看不到,你因为你吞掉了exception。
sep.WaitOne();
sep.Release(); 注释掉,结果发现,执行到了几百次就卡住了,程序无法执行下去,就像这个程序死了似的,贴图佐证:
跟sep.Release(); 那两行注释掉就那么难吗?
实在搞不懂你这里用Semaphore来做什么,如果你真的控制并发度应该由Parallel.Invoke ParallelOptions来控制啊。
还有,你的程序问题很多,很多代码写的很随意的, 下面的代码要它干嘛的?根本起不到作用。
if( this.InvokeRequired ) // 返回值为 true,表示来自 UI 线程;
//if ( true ) // 返回值为 true,表示来自 UI 线程;
{
Object[] value = { this.txtShow };
this.Invoke(this.sf, value);
}另外,我就好奇为什么你能在main thread之外更新线程了,原来你用了CheckForIllegalCrossThreadCalls,这????
//if ( true ) // 返回值为 true,表示来自 UI 线程;
{
Object[] value = { this.txtShow };
this.Invoke(this.sf, value);
}
根本不起作用,是真的,感谢赐教。使用:CheckForIllegalCrossThreadCalls 是因为我是用线程启动并行程序的,这种方式可行,因为控制台程序也是用这种方式启动的。我可以把代码传给你。你帮我看看,可否?我QQ:756385819