假设我们有一个访问远程数据库的方法调用,大约需要1秒钟来完成并返回DataTable
(下面模拟):
DataTable GetData()
{
Thread.Sleep(1000); // simulated delay
var dt = new DataTable("DataTable");
dt.Columns.Add("DateTime", typeof(DateTime));
dt.Columns.Add("Value", typeof(double));
var rand = new Random();
var date = new DateTime(2016, 1, 1);
for (int i = 0; i < 1000; i++)
{
dt.Rows.Add(date, rand.NextDouble() * 100);
date = date.AddHours(12);
}
return dt;
}
从此方法返回的DataTable用于使用单行系列填充Chart
。为什么此代码显示正确,格式正确的DateTime X-Axis标签:
async void MainForm_Load(object sender, EventArgs e)
{
var data = GetData();
chart.DataSource = data;
chart.DataBind();
}
并且此代码显示错误的,未格式化的X轴标签?
async void MainForm_Load(object sender, EventArgs e)
{
var data = await Task.Run(() => GetData());
chart.DataSource = data;
chart.DataBind();
}
请注意,即使使用第二个版本,删除Thread.Sleep()
调用也可以解决此问题。
答案 0 :(得分:1)
答案在于chart.Series[0].XValueType
首先,几个陈述:
XValueType
为Auto
,如果未明确指定,则会在Paint
事件之前的某处解析为特定类型。
这不是显而易见的事情,我通过反编译来源找到它;如果你想跟随我的研究,这里有一些里程碑:
Chart
构造函数:
this._dataManager.Initialize();
DataManager.Initialize
:
chartImage.BeforePaint += ChartPicture_BeforePaint
DataManager.ChartPicture_BeforePaint
DataManager.PrepareData
Series.PrepareData
=&gt;
if (this._xValueType == ChartValueType.Auto) { this._xValueType = ChartValueType.Double;
DataBind
会尝试根据Auto
将DataSource
解析为特定类型。如果不 Auto
,则不会尊重DataSource
中的数据类型。
好的,你的样本中发生了什么:
当你不使用任务时,Form_Load
的整个身体同步执行;当您在图表上致电DataBind
时,其Auto
为XValueType
,并根据提供DateTime
解析为DataSource
。
当您使用睡眠任务时,Paint
事件会在您初始化DataSource
之前发生,这会将XValueType
解析为Double
。在此之后绑定DataSource时,它使用DateTime
的浮点表示。
如何修复所有混乱?有很多方法,但所有方法都基于图表值类型:
Form_Load
DataBind
DataBind