老实说,我在线程方面有点蹩脚;)所以我要求一点帮助。
让我们假设,我们可以通过某种控制来绘制一些图表。还有一种方法可以在此控件上绘制图表。问题是图表方法只能访问控件的一个字段,我们需要在图表准备好时刷新控件。
所以让我们假设我们的控制看起来像这样:
class ChartingControl : System.Windows.Forms.Control
{
public Canvas canvas;
public void Refresh();
/*
... other fields/methods
*/
}
其中Canvas
是用于绘制图像的类(类似图形)
图表方法只能访问canvas
对象(我们无法更改它),所以看起来像这样:
public static void DrawChart(canvas)
{ /* draw */ }
可以从单独的线程,后台工作程序等调用此方法......我需要将其与主线程同步,并在图表准备就绪时调用Refresh()
。
现在图表准备就绪后,我在画布对象上设置了一个标志
public static void DrawChart(canvas)
{ /* draw */
canvas.Tag = true; // chart is ready
}
我有一个后台工作人员在图表控件内部运行并在canvas.Tag
字段发生变化时进行监听,如果是,则调用Refresh()
但似乎我的方法有点挣扎,容易失败等......有没有更好的方法来改进它?
限制:
- 我们无法修改Canvas
课程。我们唯一可以使用的是Tag
字段(类型为object
)
- 我们可以修改ChartingControl
类和绘图方法
- 可以有许多图表控制
- 我们无法控制DrawChart
的调用方式。它可以在单独的线程中调用,也可以不调用。它被称为其他地方。我们所能做的就是创建控件和DrawChart方法并尝试以某种方式将它们联系起来
解决方案
好的,我这样解决了:在ChartingControl
我创建了一个ManualResetEvent manualReset
和一个后台工作者。
Bacground工作人员等待manualReset
:
void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
manualReset.WaitOne(); // Wait for a chart to be ready
}
并最终调用Reset()方法
void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
Refresh();
}
我在manualReset
内传递canvas.Tag
对象,在绘图方法中,当图表准备就绪时,我调用manualReset.Set();
来传递图表准备就绪的信号。
答案 0 :(得分:1)
好的,我这样解决了:在ChartingControl
我创建了一个ManualResetEvent manualReset
和一个后台工作者。
Bacground工作人员等待manualReset
:
void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
manualReset.WaitOne(); // Wait for a chart to be ready
}
并最终调用Reset()方法
void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
Refresh();
}
我在manualReset
内传递canvas.Tag
对象,在绘图方法中,当图表准备就绪时,我调用manualReset.Set();
来传递图表准备就绪的信号。
答案 1 :(得分:0)
假设您处理对Canvas对象的访问同步,我建议您执行
myChartingControl.Invoke(new Action(myChartingControl.Refresh));
来自另一个绘制图表的线程
答案 2 :(得分:0)
BackgroundWorker会帮助您
void StartDrawChart (){
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.RunWorkerAsync()
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.Refresh();
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
DrawChart(this.canvas);
}