返回首页

{S0}
{S1}简介
本文提出了一种控制创建线程,并显示进度和从线程发送的任何消息。背景
运行多个线程,看到的地位,他们一直是相当长的一段棘手的问题。最主要的是,你不能访问任何正在由主(UI)线程控制。这包括所有形式显示的部分和它的属性和变量。
。NET框架2.0已帮助引进BackgroundWorker类清理一些。这个类允许你运行一些代码在自己的线程。这允许你的用户界面保持响应代码运行时。它做什么
这个控件可以很容易地修改,以用来监视/控制一批可以同时进行操作。一些例子:文件传输图像处理中的目录处理屏幕抓取
每个线程可以发送自己的消息回容器。容器在网格中显示这些消息,正在运行的线程。
线程容器实际上没有调节好。在启动线程,你可以设定你想同时运行的线程数量。我希望最终使这个属性的动态,以便它可以动态改变。它不会做
这个控制是专为不更新UI已经显示的是什么以外的项目。如果您需要渲染对象和更新屏幕,您将需要修改的方式运作。这可能是另一篇文章。它如何工作
每个线程都代表一个ThreadView从UserControl继承。这ThreadView包含了一个BackgroundWorker。当ThreadContainer.Start方法被调用时,它创建,因为它可以尽可能多线程(并发或TotalThreads,如果是并发症少)。 ThreadViews是停靠到顶部,使他们都显示很好,扩大ThreadContainer的宽度。在创建新的ThreadView,显示它和启动它。它的工作原理,它会引发JobEvent事件。这个消息传递到容器和ThreadContainer存储在它的DataTable。
每个ThreadView包含一个JobCompleted事件的通知,这是做ThreadContainer。如何使用代码
我已经瓜分分为两个项目的控制和测试应用程序的代码。所以,如果你平时喜欢看的代码和形式,在运行它之前,然后你开盘后该项目做的第一件事是建立,或者会因为我已经剥离出来的信息,使下载更小的错误。ThreadView类
目前的代码休眠的毫秒随机数的100倍。完全没有用处。 ThreadView的类和worker_DoWork方法。您可以更改此代码做任何你想它做。
下面是代码。我省略了一些简洁的意见。

private void worker_DoWork(object sender, DoWorkEventArgs e)

{

    for (int i= 0; i < 100; i++) 

    {

        //this checks to see if the user pressed the cancel button

        if(worker.CancellationPending)

            break;



        worker.ReportProgress(i, "Progress:" + i.ToString());



        try

        {

            Thread.Sleep(r.Next(0, _maxSleep));

        }

        catch 

        {

            // You really want to do a better job than I did with error handling    

        }

        OnJobEvent(new JobEventEventArgs(ThreadName, "Progress: " + i.ToString()));

    }

}

有两个函数调用,您不必担心:{C}
这条线设置进度条的位置,以及上面的进度条的文本。
OnJobEvent(new JobEventEventArgs(ThreadName, "Progress: " + i.ToString())); 

发送的任何消息,你想回的ThreadContainer。
这就是它!更改代码,做你想要它做的和进度条和消息添加到您的邮件和你做!属性和构造
目前,我传递的最大时间,我想线程睡在通过属性,但你可以定义任何属性,你想,或更改的构造,并把它们作为参数传递。你所要做的是确保你传递到ThreadContainer以及ThreadView类。或者你也可以传递一个值的ThreadView(即一个DirectoryInfo),它为您计算值(DirectoryInfo.GetFiles()。GetUpperBound(0))。控制ThreadView进度条最大
目前,我已经设置为100 bar最大,但如果您正在使用的对象的数量也不是100,你有3种选择:你正在做的迭代的数量和当前索引的整数除法。传递对象,你要工作(即DirectoryInfo的)到ThreadView构造,并计算出最大。 (DirectoryInfo.GetFiles()。GetUpperBound(0))。通入一个属性或构造函数的参数为​​线程的最大值。历史三月十四日,2008年:战后初期

回答

评论会员:auldh 时间:2011/12/16
本文介绍了我要找的,但我在失去了它是如何工作的。我试图了解什么是真正更新的进度。

我需要在我的C#项目中调用3 progressbars。我没有为线程建立一个"DLL"。我的应用程序调用以线性方式的多种功能。
我想给一个状态的具体progressbars作为函数被调用,并处理它的请求。我的头是旋转与此线程(调用的BackgroundWorker)。

在您的项目称之为"OnJobEvent(新JobEventEventArgs(ThreadName,"进展:"i.ToString ()));"打电话给你的线程类。你可以帮助我理解它是如何可以模仿你在做什么呢?

/ /示例代码...
  ; 私人无效ListLDN_Start(字符串[]文件名,BackgroundWorker的
工人,DoWorkEventArgs E)
{
/ /开始conerting到一个以逗号分隔的文件
listldn   ;
/ /开始的机构的工作 lcount = build_master_gspfile(文件名);
 60;
build_master_gsparray(lcount,工人,E); compare_files(lcount,文件名);

/ /完成机构的工作 }

& #160; 私人INT build_master_gspfile(字符串[]文件名)
{
  ; INT lcount = 0; / /文件列表incrementer穿行
文件列表
字符串数据= NULL; / / RA DTA字符串从输入文件读取,然后按
在输出中文件存储后
字符串TEMP1 = NULL,TEMP2 = string.Empty,site_number = NULL;
&# 160; INT逗号= 0,报价= 0,= 0;
  ; BOOL PEG = FALSE; / /用这个来衡量,如果一个记录匹配

 0;lcount = 0;

/ /主文件存放在程序目录。
& #160;StreamWriter的SW =新的StreamWriter(master_file);
  ; 尝试
  ; {
为(lcount = 0; lcount LT; filenames.Length; lcount)
{ worker.ReportProgress(的ISite / 16); & #160; (sinput.Peek()} / /而GT = 0)
/ / PEG不转有一个
错误GSP文件
&# 160; / /自己的网站数量
& #160; (PEG == FALSE)
  ; {
 0; MessageBox.Show("进程停止,因为本地站点
数量("TEMP1
  ; ")是在它自己的文件丢失:"
文件名[lcount]
"程序错误,系统中止.");{ BR} Application.Exit();
&# 160; }
} / /(lcount = 0; lcount LT; filenames.Length; lcount)
}
& #160; (异常ERR)
{
  ; EF =新的错误文件错误文件()
& #160;
& #160;
}
sw.Close()
返回lcount;
  ;} / /私人无效build_master_gspfile()

 0; 私人无效build_master_gsparray(INT lcount,BackgroundWorker的
工人,DoWorkEventArgs E)
 0;{
/ /打开普惠制的主文件并载入主普惠制数组
  ;INT的ISite = 0,iElements = 0,iTGSP = 0,iComma = 0;
&# 160; StreamReader的mgsp =新的StreamReader(master_file)
mgsp_count = 0; / /初始化
elemenst计数存储在GSPS
&# 160; / /主普惠制阵列

& #160; / / mater_file逗号分隔和引用定义的文本格式
/ /需要读取每一行,并提取逗号元素,
填充
  ; / / master_array(#站点,#元素)
(mgsp.Peek()> = 0)
 0; {
  ; (iElements == 98安培;放大器; rBngsp.Checked == TRUE)
 60; {
&# 160; iTGSP = Convert.ToInt16(master_gsp的ISite,1]);
 0; tgsp_array [iTGSP] ="1";
  ;
worker.ReportProgress(的ISite / 16);  ; 的ISite;
 60; = 0;
  ; iElements = 0;
& #160; iPlace = 0;
 0; }
&# 160; 如果(iElements GT = 96安培;放大器; rBListLDN.Checked == TRUE)
 0; {
 60; (iElements == 96)
& #160; {
master_gsp的ISite,96] ="";
& #160; master_gsp的ISite,97] ="";
&# 160; }
(iElements == 97)
  ; master_gsp的ISite,97] ="";
iTGSP = Convert.ToInt16(master_gsp的ISite,1]);
&# 160; tgsp_array [iTGSP] ="1";
&# 160;
worker.ReportProgress(的ISite / 16);  60; 的ISite;
= 0;
 60; iElements = 0;
  ; iPlace = 0;
}
/ /为(int i = 0;的ISite LT; lcount; I)
(的ISite == lcount)
&# 160; 打破;
 60; (mgsp.Peek()} / /而GT = 0)
  ; mgsp.Close()
 60; mgsp_count =的ISite;
} / /私人无效build_master_gsparray(INT lcount)
评论会员:MaxGuernsey 时间:2011/12/16
这是好事。我会建议重构某种抽象接口到自己的服务从UI线程管理部分。

这有两个好处:

1。 UI对象becoms简单得多,它才真正需要的进度和错误信息。
2。的人已经工作的经理可以简单地使用他们的用户界面,提供UI组件所需的接口]兼容。

最大根西岛,三
管理成员,六角软件有限责任公司
{A2}
{A3}
评论会员:R2B2 时间:2011/12/16
最大,

我一直在思考如何使更容易使用,以及增加功能。我喜欢你的想法更好地,虽然。我不知道我会怎样实现该接口。你将如何链接的线程作业管理? ThreadConainer类暴露适配器的集合?


理查德
评论会员:MaxGuernsey 时间:2011/12/16
R2B2写道:我不知道我会怎样实现该接口。

我能猜到。
这是你的意图的产物,所以你将不得不作出最后的通话。
什么主题视图中真正需要知道的?这需要了解一个作业,并说工作公开做的工作总量,目前的工作完成后,状态行。

是什么主题货柜真正需要知道的?它需要知道,有一件事,管理工作,它需要从那个东西能够得到一个工作清单。它也需要知道如何创建Thread对象,将它们链接到个人的工作。BR}
这样的想法,将创建一些最起码的服务接口类所消耗的,然后加以实施。你可能甚至不小心加以实施。
你可能只是模拟这些接口的实现,用于演示目的,并把它作为"读者的练习",以实现这些接口。
一旦你有一个抽象的接口绑定到你的意见,唯一的问题留给参加的是同步的。我建议,他们都是线程安全的作业管理和工作接口"合同的一部分。然后,你可以设置线程的容器,和轮询所有的工作在一些合理的,但非侵入性的间隔(30ms的,例如)
一个计时器
R2B2写道:你将如何链接的线程作业管理

我想后面的工作经理封装线程,或者也许封装工作背后的每个线程。现在你出现排队作业系统工作线程。这很好,所以只要没有显著一段时间的工作块。您asynchronization封装背后你的工作界面将允许您(一)改变你怎么做容易,(二)模拟出来,和(c)动态调整你怎么做(如:让使用者选择做
系统工作线程或与它们自己的线程)。
R2B2写道:ThreadConainer类揭露适配器的集合?

适配器不会开始发挥作用,直到别人使用你的代码已经实施了自己的作业管理。然后,他会写他的作业管理适配器,符合你的界面和它插入到你的类。

这是一个漫长的的职位。这一切有意义吗?

最大根西岛,三
管理成员,六角软件有限责任公司
{A2}
{A3}
评论会员:R2B2 时间:2011/12/16
感谢您的反应最大,

是的,它没有意义。我的意图是创建一个通用的控制,人们可以拖到其形式和写一点代码,并在该呼叫火的进度和错误事件,在任何需要的地方。这就是说,它是越来越清楚了,我已经创建了可能不是最有用的东西。
我会思考这一点,并给您回复。

理查德
评论会员:MaxGuernsey 时间:2011/12/16
您所创建的,是非常有用的,理查德。我只是建议使它更在较小的部分,它通过提供有用的方式。你可以有你的蛋糕,吃它,太。这是软件设计的美感。如果你想要的东西,很容易使用,但你也希望人们能够改变它的某些部分的行为方式,你可以将它分割成小块,然后为每个服务所依赖的默认实现。

例如:如果你定义了一个作业容器视图和作业管理服务合同,所有你所要做的的是使其视图选择一个默认的工作替代的情况下,经理实施,你会得到你寻求简单的使用特点使用此工具,插在自己的一组行为的人的能力。

最大根西岛,三
管理成员,六角软件有限责任公司
{A2}
{A3}
评论会员:R2B2 时间:2011/12/16
我要使其更加有用。我相信,我理解你在说什么。我相信您所提出的建议,使用WCF以上的IPC通信线程?


理查德
评论会员:MaxGuernsey 时间:2011/12/16
差不多:我说你从另一部分封装的一部分,这样它会更容易切换到WCF,或任何其他的解决方案,应该有人想这样做。

最大根西岛,三
管理成员,六角软件有限责任公司
{A2}
{A3}
评论会员:R2B2 时间:2011/12/16
啊哈。这是我理解你是说。拉出作业处理程序的线程管理和,然后创建一个接口,可以列出的工作和他们的状态。控制扫描

我试图去相反的方向和线程时,他们改变状态,通知控制。如果我参加了线程管理,彻底,并成立了自己的合同中添加/更新/删除线程意见的IPC通道,更新的整体状态。可以设立一个附加通道,发送取消返回到线程。

理查德
评论会员:MaxGuernsey 时间:2011/12/16
我真的不知道很多有关WCF。人们能够以换出他们使用WCF解决方案的线程管理解决方案,你建议?

我有没有反对通知控制的线程。它可能是理想的,也可能不会,这取决于你正在做的工作和其他因素的大小。控制实现{A10}]。如果您的控件实现一些接口,你写这表明采取的最新进展,你可以很容易的路线他们通过控件的BeginInvoke和EndInvoke的能力。

例如,如果所有控件都实施这样一个接口:
公共接口AcceptsProgressReport
{
无效的UpdateProgress(INT workDone,INT TOTALWORK字符串statusMessage);
}
... ...然后你的工作封装使用{A11}],通知该接口的实现时,他们的进步已经改变。然后,控制"的UpdateProgress方法可以同步实际updatin使用Control.BeginInvoke UI到UI线程的任务。

最大根西岛,三
管理成员,六角软件有限责任公司
{A2}
{A3}
评论会员:R2B2 时间:2011/12/16
你可以做什么与IPC(进程间通讯)是您可以创建在代码中的对象,这是我的代码是为obect代理。该代理通过命名管道发送一个消息,和我对象的副本调用的方法。

我到他们两人将checky,让你知道。

感谢您的所有的输入,

理查德
评论会员:MaxGuernsey 时间:2011/12/16
这听起来很酷。它是一种选择,我认为,人们希望聘请。我的选择,如果我是使用你的库 - 它有一个很好的机会,我想如果我写一个UI - 将有一种工作,我可以插入我的作业管理。理想的情况下,我可以有许多不同种类的职位 - 一些过程中,一些进程外,一些在不同的应用程序域 - 所有通过一个经理和管理都通过一个华而不实的UI组件

我期待着听你拿出。

最大根西岛,三
管理成员,六角软件有限责任公司
{A2} {A3}
评论会员:stuart_roberts 时间:2011/12/16
!嗨
从我的角度来看,这是一个非常有趣的的讨论主题,有一个在这一阶段的学术兴趣,但很少真正的知识多线程操作,其监测。

我可以做一个完全不知情的建议吗?它可能为你2扎堆创建这个讨论的文章,​​也许扔在一个更详细的?我认为这样的"来来回回"重达到软件设计的优点和缺点是,往往是从视图中隐藏的东西,让人们奇怪,为什么选择似乎没有多大意义的开发。

任何,只是一个念头。请随时告知我们如何控制和文章的进展,作为落脚点有趣的设计很容易!

斯图尔特R
评论会员:MaxGuernsey 时间:2011/12/16
R2B2:让我知道如果你有兴趣

我的电子邮件地址是最大[在] hexsw [点​​]的COM。

最大根西岛,三
管理成员,六角软件有限责任公司
{A2}
{A3}
评论会员:R2B2 时间:2011/12/16
这听起来对我好。其实我也一直在思考的几篇文章。我看过的一些技术,也有可能工作的思路。具体使用IPC通道,远程同箱的沟通,并使用WCF和MSMQ来处理分布式状态/消息,甚至纳入一个TreeView显示多个类别被监视的东西地位。

马克斯,我会给你一个电子邮件不久,但它可能是一个位之前的文章出来{S2}

欢呼声,
理查德
评论会员:汤普森 时间:2011/12/16
的文章。不过,我有问题的代码建设。
我得到以下错误:

属性\ licenses.licx(1):LC0003错误:无法解析类型DevExpress.XtraEditors.LabelControl,DevExpress.XtraEditors.v7.3

有什么建议?
评论会员:会员1556192 时间:2011/12/16
Juste在licenses.licx删除行从控制项目。
评论会员:R2B2 时间:2011/12/16
感谢会员1556192。我很抱歉,我在那里的参考。我已经更新在压缩文件中的代码。

理查德
评论会员:游客 时间:2011/12/16
Ciupaz:|嗨,我有同样的问题,这个错误:属性\licenses.licx(1,0):LC0003错误:无法解析DevExpress.XtraTreeList.TreeList类型',DevExpress.XtraTreeList.v8.2,版本=8.2.3.0,文化=中性公钥=9b171c9fd64da1d1'在我的电脑,但在生产服务器。也许DevExpress吹必须安装在本机不仅在我的电脑?在adavance感谢。路易吉
R2B2
评论会员:游客 时间:2011/12/16
路易吉,当我第一次创建项目时,我用的DevExpress控制。后来我才意识到,不会好张贴与第三方工具的文章,所以我就拿出来。即使我把它引用的DLL,许可证仍然在属性\licenses.licx文件。如果你去到该文件,并删除文件(我认为这是唯一一个)行并保存该文件应该编译的罚款。让我知道如果您有任何其他问题。理查德
Ciupaz
评论会员:游客 时间:2011/12/16
感谢回应理查德我已经把一个单独的文件夹中的DLL,该DLL的参考我的项目点。现在它的作品。路易吉"
汤普森
评论会员:游客 时间:2011/12/16
感谢。这做的伎俩。的问候,史蒂夫