C# 在创建对象的线程上调用方法
假设我在线程T上创建了一个对象O。如何从线程T的对象O内部获取并调用该线程上的方法?。这样,创建对象的窗体就不必执行以下操作:C# 在创建对象的线程上调用方法,c#,multithreading,events,C#,Multithreading,Events,假设我在线程T上创建了一个对象O。如何从线程T的对象O内部获取并调用该线程上的方法?。这样,创建对象的窗体就不必执行以下操作: private void ChangeProgress(int value) { progressBar1.Value = value; } void FD_ProgressChanged(object sender, DownloadEventArgs e) { if (InvokeRequir
private void ChangeProgress(int value)
{
progressBar1.Value = value;
}
void FD_ProgressChanged(object sender, DownloadEventArgs e)
{
if (InvokeRequired)
{
Invoke(new Action<int>(ChangeProgress), new object[] { e.PercentDone });
}
else ChangeProgress(e.PercentDone);
}
private void ChangeProgress(int值)
{
progressBar1.值=值;
}
void FD_ProgressChanged(对象发送方,下载事件参数e)
{
如果(需要调用)
{
调用(新操作(ChangeProgress),新对象[]{e.PercentDone});
}
其他变更进度(如完成百分比);
}
这很难看,需要使用该对象的人找出哪些事件在创建该对象的同一线程上引发,哪些没有引发,然后添加
if(InvokeRequired)…或者在没有引发的线程上添加代码,或者只在每个事件处理程序上添加代码。我认为,如果对象本身负责在正确的线程上调用事件,那么它将更加优雅。这可能吗?使用BackgroundWorker类。它解决了所有这些问题。请注意ReportProgress事件。您必须像跟踪一样跟踪它
class Foo {
private readonly Thread creatingThread;
public Foo() {
this.creatingThread = Thread.CurrentThread;
}
}
如果你不这样做,就没有办法知道。但你这样做的事实是一种气味。考虑使用.有一些事情需要考虑:
- 您需要在创建它的线程的
对象O
中保留一个引用。可能在使用Thread.Current
静态属性的构造函数中
- 该线程需要有一个与之关联的
SynchronizationContext
。(通常,UI线程都有它。为您创建的自定义线程创建一个线程并不容易。)
- 要在该线程上调用方法,需要在该线程的
SynchronizationContext
上使用Send()
或Post()
方法
在
这是我的通用版本:
private void RaiseEventAsync(Delegate handler, object e)
{
if (null != handler)
{
List<Delegate> invocationList = handler.GetInvocationList().ToList();
foreach (Delegate singleCast in invocationList)
{
System.ComponentModel.ISynchronizeInvoke syncInvoke =
singleCast.Target as System.ComponentModel.ISynchronizeInvoke;
try
{
if ((null != syncInvoke) && (syncInvoke.InvokeRequired))
syncInvoke.Invoke(singleCast,
new object[] { this, e });
else
singleCast.Method.Invoke(singleCast.Target, new object[] { this, e });
}
catch
{ }
}
}
}
这解决了我的问题,而无需使用并非总是需要的BackgroundWorker
(比如在我的案例中,我正在对一个已经使用不同线程对象的类进行子类化)。如何获得同步上下文
?我知道线程是一个UI线程,所以它必须有一个,但你怎么得到它?太好了!这样,您的代码将永远与WinForms绑定!或您可以使用任务并行库并保持UI独立性。实际上,我将听取Hans的意见,并使用BackgroundWorker
重写该类。我可以绕过报告进度
来通知任何我想通知的内容。
protected void OnProgressChanged(DownloadEventArgs e)
{
RaiseEventAsync(ProgressChanged, e);
}