[★]WinForm中,主线程如何优雅的控制子线程?
在Winform界面中,为了客户的体验或者其他原因,我们总是将耗时的事务在另外新开的线程中进行操作,那么对于这些线程的控制,涉及到下面的这些情况,各位都是用什么方法解决呢?
1. 启动线程;
2. 线程间通讯;
3. 线程终止;
4. 线程中的异常处理;
欢迎大家一起讨论下,我发现在这块现在感觉很难驾驭。
当然,如果还有其他没有提到的,还请兄弟们直接给出。多谢!
————————————————————————————————
BTW:这个坛子里面的搜索现在很难用,我没有办法找到我想要的信息,不知道各位是否有同样的问题?
[解决办法]
● 如果是需要很频繁的开线程,会使用线程池(微软的或自己写的),目前我用自己写的
● 对于线程间的通信,主要是通过线程同步或者回调方法(或者说是委托)来实现
● 线程的终止,用事件AUTORESET之类
● 线程中的异常通过事件传回到主线程处理或者是写错误日志便于进一步跟踪问题
[解决办法]
委托
[解决办法]
参考愚翁专栏文章CSDN第一期总结之三:Thread的问题
[解决办法]
[解决办法]
一般帮助里的方法就可以了。
[解决办法]
http://msdn.microsoft.com/zh-cn/library/system.componentmodel.backgroundworker.aspx
.NET Framework 类库
BackgroundWorker 类
更新:2007 年 11 月
在单独的线程上执行操作。
BackgroundWorker 类允许您在单独的专用线程上运行操作。耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面 (UI) 似乎处于停止响应状态。如果您需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用 BackgroundWorker 类方便地解决问题。
若要在后台执行耗时的操作,请创建一个 BackgroundWorker,侦听那些报告操作进度并在操作完成时发出信号的事件。可以通过编程方式创建 BackgroundWorker,也可以将它从“工具箱”的“组件”选项卡中拖到窗体上。如果在 Windows 窗体设计器中创建 BackgroundWorker,则它会出现在组件栏中,而且它的属性会显示在“属性”窗口中。
若要设置后台操作,请为 DoWork 事件添加一个事件处理程序。在此事件处理程序中调用耗时的操作。若要启动该操作,请调用 RunWorkerAsync。若要收到进度更新通知,请对 ProgressChanged 事件进行处理。若要在操作完成时收到通知,请对 RunWorkerCompleted 事件进行处理。
说明:
您必须非常小心,确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。
BackgroundWorker 事件不跨 AppDomain 边界进行封送处理。请不要使用 BackgroundWorker 组件在多个 AppDomain 中执行多线程操作。
如果后台操作需要参数,请在调用 RunWorkerAsync 时给出参数。在 DoWork 事件处理程序内部,可以从 DoWorkEventArgs.Argument 属性中提取该参数。
[解决办法]
多线程 没有优雅的代码, 只有优雅的表现
[解决办法]
收藏了
[解决办法]
[解决办法]
我也很期待高手优雅的表现。。。。
[解决办法]
学习
[解决办法]
up
[解决办法]
收藏先
[解决办法]
学习。
[解决办法]
期待
[解决办法]
学习,帮顶下。
[解决办法]
好东西收藏了
[解决办法]
学习,帮顶
[解决办法]
愚翁的文章很好
[解决办法]
好贴,顶下,
[解决办法]
http://blog.csdn.net/Knight94/archive/2006/08/24/1111267.aspx
好文章
[解决办法]
灌水
[解决办法]
委托安全调用
用BackgroundWorker控件
参考
参考
[解决办法]
顶下
[解决办法]
关注中,多线程的确不好搞,期待大师指点。
[解决办法]
mark
[解决办法]
mark up
[解决办法]
顶
[解决办法]
看了,学习,谢谢,
[解决办法]
多线程一定要用,我还没在工作中使用
[解决办法]
学习了!
[解决办法]
mark
[解决办法]
不懂
[解决办法]
异步编程设计模式
[解决办法]
收藏,需要时再来学习
[解决办法]
单CPU的另开线程有用么?
[解决办法]
[解决办法]
学习中
[解决办法]
关注中。。。。
[解决办法]
up
[解决办法]
支持并学习
[解决办法]
学习
[解决办法]
mark,正需要这方面的参考资料了
[解决办法]
BackgroundWorker 算是使用比较简便的
[解决办法]
1. 启动线程;
Thread.Start(参数object);
或者用对象提供的BeginXXXX()这种都是异步,也算多线程启动.
2. 线程间通讯;
委托,事件这些比较常用,并且对object的多线程处理需要谨慎,可能用到lock(object){}.
3. 线程终止;
对于线程终止判断,可以用Thread.ManualEvent().Reset()/Set()/WaitOne()方法来判断和等待.
4. 线程中的异常处理;
还是写log吧,多线程debug比较难,还是逐步log比较好.
[解决办法]
留个记号
[解决办法]
这个例子很不错。楼主粘过去调试,再结合MSDN。。会发现线程同步控制的魅力所在。
下面的示例演示使用 lock 关键字以及 AutoResetEvent 和 ManualResetEvent 类对主线程和两个辅助线程进行线程同步。有关更多信息,请参见 lock 语句(C# 参考)。
该示例创建两个辅助线程。一个线程生成元素并将它们存储在非线程安全的泛型队列中。有关更多信息,请参见 Queue。另一个线程使用此队列中的项。另外,主线程定期显示队列的内容,因此该队列被三个线程访问。lock 关键字用于同步对队列的访问,以确保队列的状态没有被破坏。
除了用 lock 关键字来阻止同时访问外,还用两个事件对象提供进一步的同步。一个事件对象用来通知辅助线程终止,另一个事件对象由制造者线程用来在有新项添加到队列中时通知使用者线程。这两个事件对象封装在一个名为 SyncEvents 的类中。这使事件可以轻松传递到表示制造者线程和使用者线程的对象。SyncEvents 类是按如下方式定义的:
- C# code
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
public class SyncEvents
{
public SyncEvents()
{
_newItemEvent = new AutoResetEvent(false);
_exitThreadEvent = new ManualResetEvent(false);
_eventArray = new WaitHandle[2];
_eventArray[0] = _newItemEvent;
_eventArray[1] = _exitThreadEvent;
}
public EventWaitHandle ExitThreadEvent
{
get { return _exitThreadEvent; }
}
public EventWaitHandle NewItemEvent
{
get { return _newItemEvent; }
}
public WaitHandle[] EventArray
{
get { return _eventArray; }
}
private EventWaitHandle _newItemEvent;
private EventWaitHandle _exitThreadEvent;
private WaitHandle[] _eventArray;
}
public class Producer
{
public Producer(Queue <int> q, SyncEvents e)
{
_queue = q;
_syncEvents = e;
}
// Producer.ThreadRun
public void ThreadRun()
{
int count = 0;
Random r = new Random();
while (!_syncEvents.ExitThreadEvent.WaitOne(0, false))
{
lock (((ICollection)_queue).SyncRoot)
{
while (_queue.Count < 20)
{
_queue.Enqueue(r.Next(0,100));
_syncEvents.NewItemEvent.Set();
count++;
}
}
}
Console.WriteLine("Producer thread: produced {0} items", count);
}
private Queue <int> _queue;
private SyncEvents _syncEvents;
}
public class Consumer
{
public Consumer(Queue <int> q, SyncEvents e)
{
_queue = q;
_syncEvents = e;
}
// Consumer.ThreadRun
public void ThreadRun()
{
int count = 0;
while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1)
{
lock (((ICollection)_queue).SyncRoot)
{
int item = _queue.Dequeue();
}
count++;
}
Console.WriteLine("Consumer Thread: consumed {0} items", count);
}
private Queue <int> _queue;
private SyncEvents _syncEvents;
}
public class ThreadSyncSample
{
private static void ShowQueueContents(Queue <int> q)
{
lock (((ICollection)q).SyncRoot)
{
foreach (int item in q)
{
Console.Write("{0} ", item);
}
}
Console.WriteLine();
}
static void Main()
{
Queue <int> queue = new Queue <int>();
SyncEvents syncEvents = new SyncEvents();
Console.WriteLine("Configuring worker threads...");
Producer producer = new Producer(queue, syncEvents);
Consumer consumer = new Consumer(queue, syncEvents);
Thread producerThread = new Thread(producer.ThreadRun);
Thread consumerThread = new Thread(consumer.ThreadRun);
Console.WriteLine("Launching producer and consumer threads...");
producerThread.Start();
consumerThread.Start();
for (int i=0; i <4; i++)
{
Thread.Sleep(2500);
ShowQueueContents(queue);
}
Console.WriteLine("Signaling threads to terminate...");
syncEvents.ExitThreadEvent.Set();
producerThread.Join();
consumerThread.Join();
}
}
[解决办法]
.
[解决办法]
这个问题很值得考虑
[解决办法]
[解决办法]
1. 启动线程;
Thread.Start(参数object);
或者用对象提供的BeginXXXX()这种都是异步,也算多线程启动.
2. 线程间通讯;
委托,事件这些比较常用,并且对object的多线程处理需要谨慎,可能用到lock(object){}.
3. 线程终止;
对于线程终止判断,可以用Thread.ManualEvent().Reset()/Set()/WaitOne()方法来判断和等待.
4. 线程中的异常处理;
还是写log吧,多线程debug比较难,还是逐步log比较好.
我会的也就这样的东西
是不是太简单了
[解决办法]
Mark
[解决办法]
学习中
!!
[解决办法]
[解决办法]
mark&&up
[解决办法]
学习,顶起来~
[解决办法]
学习
[解决办法]
收藏