zoukankan      html  css  js  c++  java
  • WPF 从其他线程中修改更新控件

    大家都知道,多线程可以大大提高WPF的反应效率,但是不幸的是,UI控件不能被多个线程同时更改。

    比如:

    代码
    public partial class Window1 : Window
    {
    public Window1()
    {
    InitializeComponent();

    CheckBox myCheckBox
    = new CheckBox();
    myCheckBox.Content
    = "A Checkbox";

    System.Threading.Thread thread
    = new System.Threading.Thread(
    new System.Threading.ThreadStart(
    delegate()
    {
    txtUpdateDownloadInfo.Text
    += "update KB download begin...." + Environment.NewLine;
    }
    ));

    thread.Start();
    }
    }

    则会抛出: The calling thread cannot access this object because a different thread owns it.的异常。

    在Winform中我们可以是设置: Control.CheckForIllegalCrossThreadCalls = false; 在加上lock可以解决此问题,但是WPF中是没有这个属性的。

    而幸运的是WPF同样提供了一个功能更大---Dispatcher。在WPF中大多数控件都是继承于DispacterObject,所以他们都具有Dispatcher属性。

    所以,解决方案:

    WPF:

    代码
    private void btnDownload_Click(object sender, RoutedEventArgs e)
    {
    if (string.IsNullOrEmpty(txtUpdates.Text))
    {
    MessageBox.Show(
    "Error, Please input the update KBNumber");
    return;
    }
    try
    {
    string[] updates = txtUpdates.Text.Split(new char[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
    foreach (var item in updates)
    {
    ParameterizedThreadStart st
    = new ParameterizedThreadStart(Download);
    Thread t
    = new Thread(st);
    t.Start(item);
    }
    }
    catch (Exception ex)
    {
    MessageBox.Show(
    "Error with :" + ex.Message);
    }
    }
    public void Download(object Kbnumber)
    {
    CopyUpdates(Kbnumber
    as string);
    }
    private void CopyUpdates(string p_updates)
    {
    Application.Current.Dispatcher.BeginInvoke(
    DispatcherPriority.Background,
    new Action(() => txtUpdateDownloadInfo.Text += "update KB" + p_updates + " download begin...." + Environment.NewLine));


    IEnumerable
    <KeyValuePair<string, string>> updateLocations = new Dictionary<string, string>();

    updateLocations
    = updateLocations.Union(UpdatesSupport.GetUpdateSource(p_updates));

    foreach (KeyValuePair<string, string> kvp in updateLocations)
    {
    try
    {
    if (!IO.Directory.Exists(IO.Path.GetDirectoryName(kvp.Value)))
    IO.Directory.CreateDirectory(IO.Path.GetDirectoryName(kvp.Value));

    if (!IO.File.Exists(kvp.Value) || IO.File.GetLastWriteTimeUtc(kvp.Value) < IO.File.GetLastWriteTimeUtc(kvp.Key))
    IO.File.Copy(kvp.Key, kvp.Value);
    }
    catch
    { }
    }

    Application.Current.Dispatcher.BeginInvoke(
    DispatcherPriority.Background,
    new Action(() => txtUpdateDownloadInfo.Text += "update KB" + p_updates + " download completed...." + Environment.NewLine));


    }

    Winform:

    代码
    public UpdateInfos()
    {
    InitializeComponent();

    DownloadPanel dp
    = new DownloadPanel();
    dp.Location
    = new Point(9, 19);
    gbxUIODT.Controls.Add(dp);

    Control.CheckForIllegalCrossThreadCalls
    = false;
    }

    private void btnUIDownload_Click(object sender, EventArgs e)
    {
    if (string.IsNullOrEmpty(txtUIUpdates.Text))
    {
    MessageBox.Show(
    "Error, Please input the update KBNumber");
    return;
    }
    try
    {
    string[] updates = txtUIUpdates.Text.Split(new char[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
    foreach (var item in updates)
    {
    ParameterizedThreadStart st
    = new ParameterizedThreadStart(Download);
    Thread t
    = new Thread(st);
    t.Start(item);
    }
    }
    catch(Exception ex)
    {
    MessageBox.Show(
    "Error with :" + ex.Message);
    }

    }

    public void Download(object Kbnumber)
    {
    CopyUpdates(Kbnumber
    as string);
    }
    public void CopyUpdates(string p_updates)
    {
    lock (this)
    {
    txtUIDonwloadInfo.Text
    += "update KB" + p_updates + " download begin...." + Environment.NewLine;
    }
    IEnumerable
    <KeyValuePair<string, string>> updateLocations = new Dictionary<string, string>();

    updateLocations
    = updateLocations.Union(GetUpdateSource(p_updates));

    foreach (KeyValuePair<string, string> kvp in updateLocations)
    {
    try
    {
    if (!Directory.Exists(Path.GetDirectoryName(kvp.Value)))
    Directory.CreateDirectory(Path.GetDirectoryName(kvp.Value));

    if (!File.Exists(kvp.Value) || File.GetLastWriteTimeUtc(kvp.Value) < File.GetLastWriteTimeUtc(kvp.Key))
    File.Copy(kvp.Key, kvp.Value);
    }
    catch
    { }
    }
    lock (this)
    {
    txtUIDonwloadInfo.Text
    += "update KB" + p_updates + " download completed...." + Environment.NewLine;
    }
    }
  • 相关阅读:
    VS code 快捷键注释不能用[!----]解决办法
    vue 文件导出demo
    vue中后台返回的是数字,前端利用字典将其转换为相对应的中文
    java.lang.UnsupportedOperationException解决方法【转】
    Java List的remove()方法陷阱
    密码至少包含数字、大小写字母、特殊字符两种以上,长度不小于8位
    获取规格内数字
    获取时间段数据
    Echarts GL初次体验
    bootstrap-datetimepicker 如何获取值(日期)
  • 原文地址:https://www.cnblogs.com/jimson/p/1925652.html
Copyright © 2011-2022 走看看