新线程作为UI线程运行

时间:2015-10-17 21:17:58

标签: c# multithreading winforms user-interface

我有一个表格" DisplayImagesForm"它在构造函数中调用函数loadImages()

public ImageScraperForm(string query, RichTextBox textBox)
{
    InitializeComponent();
    this.query = query;
    loadImages();
}

然后loadImages()函数在最后创建一个新线程:

{
   ...
   Thread thread = new Thread(readNextImage);
   thread.Start();
}

问题是该线程似乎不是作为与UI线程不同的线程运行。 readNextImage()方法从服务器加载图像需要一些时间 - 加载图像时它会阻止整个表单。这不正常,因为"线程"应该与UI线程分开运行。此外,readNextImage()函数可以修改没有Invoke((MethodInvoker)delegate的UI元素 - 不会抛出任何异常。

1 个答案:

答案 0 :(得分:-2)

如果您尝试通过互联网下载图像并将其显示在WinForm控件中;你完全错了。

不要在Form构造函数中进行任何冗长的处理;这会使你的表格没有反应。如果要在UI中显示某些内容,则应在Form的Paint事件处理程序中执行此操作。如果您尝试通过互联网下载某些内容,则应使用await,而不是Thread。线程使用CPU核心,因为互联网比CPU慢几个数量级,所以你将立即阻止它。

正确的方法是使用await在需要时加载文件。如果您在启动Load事件处理程序时需要它,那么这是一个不错的选择。

private async void YourForm_Load(object sender, EventArgs e)
{
    using (var c = new HttpClient())
    using (var resp = await c.GetAsync(@"http://uri/to/image.jpg"))
    using (var content = resp.Content)
    using (var s = await content.ReadAsStreamAsync())
    {
        _img = new Bitmap(s);
    }

    YourControl.Invalidate();
}

private void YourForm_Paint(object sender, PaintEventArgs e)
{
    if (_img != null)
        DrawToYourControl(_img);
}