C# 自定义线程修改UI(一)

在Wpf中界面显示数据的修改,都是通过UI线程完成,如果尝试从其他线程中直接修改控件的值回抛出异常,“调用线程无法访问此对象,因为另一个线程拥有该对象”。

例如:http://www.cnblogs.com/tianma3798/p/5762016.html

解决方案1:通过Invoke或者BeginInvoke将操作发送给Dispatcher 对象,委托Dispatcher去执行UI操作,每个UI控件都有Dispatcher 对象

代码实例:

Xaml代码

<ProgressBar x:Name="progressOne"
                Minimum="0" Maximum="1"
                Height="30"   Margin="10,85,10,0"
                VerticalAlignment="Top"/>
<!--绑定 进度条的值,并格式化为百分数-->
<Label x:Name="label" Content="{Binding ElementName=progressOne,Path=Value}"
        ContentStringFormat="{}{0:P2}"
        HorizontalAlignment="Left"
        Margin="110,120,0,0"
        FontWeight="Bold" Foreground="Red"
        VerticalAlignment="Top"/>

C#代码

//启动前程修改UI数据
Task.Run(() =>
{
    int i = 0;
    while (true)
    {
        i++;
        if (i == 100)
            i = 0;
        //定义修改UI委托
        Action<int> action1 = (q) =>
        {
            progressOne.Value = q/100.0;
        };
        progressOne.Dispatcher.BeginInvoke(action1, i);
        Thread.Sleep(100);
    }
});

显示:

解决方案2:使用Wpf的双向绑定,在自定义线程中修改源数据,自动通知到UI线程修改界面显示

这种方式有个好处,只关心数据的修改,界面多出使用该数据的界面自动修改

更多双向绑定:http://www.cnblogs.com/tianma3798/p/5765464.html

代码实例:

Xaml代码

<Grid>
    <Slider x:Name="slider"
            Height="30"
            Value="{Binding Path=Result,Mode=TwoWay}" Minimum="0" Maximum="100"
            Margin="35,120,25,0" VerticalAlignment="Top"/>
    <Label x:Name="label" Content="{Binding Path=Result,Mode=TwoWay}"
            ContentStringFormat="当前值:{0}"
            HorizontalAlignment="Left"
            FontWeight="Bold" Foreground="Red"
            Margin="95,165,0,0"
            VerticalAlignment="Top"/>
</Grid>

C#代码

//双向绑定数据
NumberData data = new NumberData();
slider.DataContext = data;
label.DataContext = data;
//启动线程修改绑定数据,界面内容会同步修改
Task.Run(() =>
{
    int i = 0;
    while (true)
    {
        i++;
        if (i == 100) i = 0;
        //修改双向绑定属性
        data.Result = i;
        Thread.Sleep(100);
    }
});
/// <summary>
/// 实现INotifyPropertyChanged接口,通知
/// </summary>
public class NumberData : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private int _Result;
    public int Result
    {
        get { return _Result; }
        set
        {
            _Result = value;
            if (this.PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("Result"));
        }
    }
}

更多异步修改UI:http://www.cnblogs.com/tianma3798/p/5766691.html

时间: 2024-09-29 01:23:29

C# 自定义线程修改UI(一)的相关文章

2017.12.18 Android开发之消息队列(实现子线程修改UI组件)

1.界面布局,以及组件初始化: 组件初始化: private Button button; private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button=(Button)findViewById(R.id.button)

线程操纵UI问题

WPF只允许UI线程修改UI,其他线程必须通过Invoke.委托(安全性)Winform可以开启/关闭"只允许UI线程修改UI" 在WPF中非UI线程修改UI的方法 非UI线程直接修改UI,会报错 System.InvalidOperationException:"调用线程无法访问此对象,因为另一个线程拥有该对象." 正确的做法是 Task t = new Task(() => { NameLabel.Dispatcher.Invoke(new Action(

WinForm 子线程修改主线程(UI线程)

原文http://www.cnblogs.com/SkySoot/archive/2012/03/14/2396552.html 我们先来看一段运行时会抛出 InvalidOperationException 异常的代码段: 1 public partial class TestThread : Form 2 { 3 public TestThread() 4 { 5 InitializeComponent(); 6 } 7 8 Thread thread; 9 10 void SetText(

C# WPF 使用委托修改UI控件

近段时间在自学WPF,是一个完全不懂WPF的菜鸟,对于在线程中修改UI控件使用委托做一个记录,给自已以后查询也给需要的参考: 界面只放一个RichTextBox,在窗体启动时开起两个线程,调用两个函数,每隔1秒写一次当前时间 一 界面XAML如下: <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&qu

Asp.net Core WebApi 使用Swagger做帮助文档,并且自定义Swagger的UI

WebApi写好之后,在线帮助文档以及能够在线调试的工具是专业化的表现,而Swagger毫无疑问是做Docs的最佳工具,自动生成每个Controller的接口说明,自动将参数解析成json,并且能够在线调试. 那么要讲Swagger应用到Asp.net Core中需要哪些步骤,填多少坑呢? 安装Swagger到项目 { "dependencies": { "Swashbuckle": "6.0.0-beta902", ........ 或者直接通

C# Wpf异步修改UI,多线程修改UI(二)

1.使用定时器异步修改 这是相对比较简单的方法 在Wpf中定时器使用DiapatcherTimer,不使用Timer原因: 在一个应用程序中,Timer会重复生成time事件,而DispatcherTimer是一个集成到了Dispatcher队列中的时钟,这可以使它被按照指定的时间间隔以指定的priority定期执行. 对于一个Timer时钟事件,系统并不能保证在时间间隔到达后被立即执行,但是能够确保在时间间隔到达之前不被执行.这是因为DispatcherTimer像其他操作一样被放置在了Dis

理解SynchronizationContext,如何在Winform里面跨线程访问UI控件

SynchronizationContext 类是一个基类,可提供不带同步的自由线程上下文. 此类实现的同步模型的目的是使公共语言运行库内部的异步/同步操作能够针对不同的异步模型采取正确的行为.此模型还简化了托管应用程序为在不同的同步环境下正常工作而必须遵循的一些要求.同步模型的提供程序可以扩展此类并为这些方法提供自己的实现.(来自MSDN)简而言之就是允许一个线程和另外一个线程进行通讯,SynchronizationContext在通讯中充当传输者的角色.另外这里有个地方需要清楚的,不是每个线

从setTimeout到浏览器线程机制 ,实现JS线程和UI同时执行的效果

遇到一个问题情况: ocx读取多条记录的结果集. 在js里用 for遍历. for(var i= 0;i<length;i++){ $.ajax({ 后台返回结果 处理成功, 调用更新进度条的方法. }) } 发现,总是当for全部遍历完成,才去渲染进度条控件.更改样式. 查阅N多资料更改后, 将for改为递归调用,没执行一次,渲染一次进度条,后面的JS代码放在setTimeout(function,0),这时浏览器会优先渲染UI界面,然后在执行后面的JS代码,就实现了进度条实时更新了. //更

调试与运行结果不一致?第一次运行正确,后面错误,由于多线程修改UI吗?

先说说问题背景:使用Eclipse安装android程序到手机,调试ok,达到预想效果,退出,重新打开程序,No,部分UI界面未显示,Why? 首先想到的是多线程问题,调试与运行结果不一致说明中间存在时间差,因为单步调试的时候时间会被延长,然后找原因点,程序中修改UI 的代码分两部分,1部分修改好友图像,2部分更新地图,1是通过AsyncHttpClient异步从后台取数据,2则不涉及异步问题,在线程上测试了 很久,没搞定. 今天早上过来,突然意识到,修改地图的activity是新增的,不像其他