主界面
XAML:按钮绑定命令和属性
<Grid>
<StackPanel>
<ProgressBar x:Name="ProgressBar" Height="20" VerticalAlignment="Top" Margin="10 10 10 10" Value="{Binding Progress}"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button x:Name="StartButton" Grid.Column="0" Content="start!" VerticalAlignment="Top" Margin="10 0 10 10" Command="{Binding ClickCommandStart}" IsEnabled="{Binding StartIsEnabled}" />
<Button x:Name="CancelButton" Grid.Column="1" Content="cancel!" VerticalAlignment="Top" Margin="10 0 10 10" Command="{Binding ClickCommandCancel}" />
</Grid>
</StackPanel>
</Grid>
主界面交互逻辑:
定义类ViewModel,与主界面上下文绑定。
public class ViewModel : DependencyObject
DataContext = new ViewModel();//主界面绑定数据上下文模型
定义可以被xaml绑定的命令:
public class CommandHandler : ICommand //可以被xaml绑定的命令
//UI的start按钮绑定的命令 click from XAML
public ICommand ClickCommandStart
{
get { return new CommandHandler(() => ActionStart(), canExecute); }
}
//UI的取消按钮绑定的命令
public ICommand ClickCommandCancel
{
get { return new CommandHandler(() => ActionCancel(), canExecute); }
}
定义可以被xaml绑定的属性:
//DependencyProperty 表示可以通过样式、数据绑定、动画和继承等方法设置的属性
public DependencyProperty StartIsEnabledProperty;//开始按钮可用属性
public DependencyProperty ProgressProperty;//进度属性
//使用指定的属性名称、属性类型和所有者类型注册依赖项属性。
StartIsEnabledProperty = DependencyProperty.Register("StartIsEnabled", typeof(bool), typeof(ViewModel));
ProgressProperty = DependencyProperty.Register("Progress", typeof(int), typeof(ViewModel));
//UI中start按钮绑定的 启用属性
public bool StartIsEnabled
{
get { return (bool)GetValue(StartIsEnabledProperty); }
set { SetValue(StartIsEnabledProperty, value); }
}
//进度条绑定的 进度属性
public int Progress
{
get { return (int)GetValue(ProgressProperty); }
set { SetValue(ProgressProperty, value * 10); }
}
在代码里设置属性:
StartIsEnabled = true;
Progress = 0;
UI更新线程进度:
在线程中定义两个事件:
public event Action<int> ProcessAdvanced;//汇报进度事件
public event Action<bool> WorkComplete; //工作完成事件: bool==true 表示线程被取消。 bool==false 表示线程执行完毕
开启线程时将UI的同步上下文传递给线程:
Thread thread = new Thread(worker.Work);
thread.Start(context);//将当前线程同步上下文传递给 worker线程
开启线程前绑定线程事件的处理方法:
worker.ProcessAdvanced += Worker_ProcessAdvanced;//工作线程进度事件
worker.WorkComplete += Worker_WorkComplete;//工作线程完成事件
UI的同步上下文获取:
context = SynchronizationContext.Current;//获取当前线程的同步上下文。传递给工作线程,在工作线程里传递给UI进度信号
工作线程通过UI的同步上下文触发事件:
//发送事件进度 send event abount progress 在派生类中重写时,将同步消息分派到同步上下文。
context.Send(OnProgressAdvanced, i);
//发送关于已完成工作的事件 send event about work done
context.Send(OnWorkComplete, cancelled);
//通知UI线程 工作线程进度
public void OnProgressAdvanced(object progress)
{
ProcessAdvanced((int)progress);
}
//通知UI线程 工作线程完成
public void OnWorkComplete(object cancelled)
{
WorkComplete((bool) cancelled);
}
全部代码:
namespace MultithreadingTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();//主界面绑定数据上下文模型
}
}
/// <summary>
/// Button's actions from XAML handler
/// 按钮的操作 从XAML处理程序
/// </summary>
public class CommandHandler : ICommand //可以被xaml绑定的命令
{
public event EventHandler CanExecuteChanged;
private Action action;//命令的操作
private bool canExecute;//命令是否可执行
public CommandHandler(Action action, bool canExecute)
{
this.action = action;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return canExecute;
}
public void Execute(object parameter)
{
action();
}
}
/// <summary>
/// Button's actions and multithreading work event handlers
/// </summary>
public class ViewModel : DependencyObject
{
// private ICommand click;
private bool canExecute;
private Worker worker;
private SynchronizationContext context;//提供在各种同步模型中传播同步上下文的基本功能。
//DependencyProperty 表示可以通过样式、数据绑定、动画和继承等方法设置的属性
public DependencyProperty StartIsEnabledProperty;//开始按钮可用属性
public DependencyProperty ProgressProperty;//进度属性
public ViewModel()
{
canExecute = true;
//使用指定的属性名称、属性类型和所有者类型注册依赖项属性。
StartIsEnabledProperty = DependencyProperty.Register("StartIsEnabled", typeof(bool), typeof(ViewModel));
ProgressProperty = DependencyProperty.Register("Progress", typeof(int), typeof(ViewModel));
context = SynchronizationContext.Current;//获取当前线程的同步上下文。传递给工作线程,在工作线程里传递给UI进度信号
StartIsEnabled = true;
}
//UI的start按钮绑定的命令 click from XAML
public ICommand ClickCommandStart
{
get { return new CommandHandler(() => ActionStart(), canExecute); }
}
//UI的取消按钮绑定的命令
public ICommand ClickCommandCancel
{
get { return new CommandHandler(() => ActionCancel(), canExecute); }
}
//单击开始操作(第一个线程) click start action (first thread)
public void ActionStart()
{
Console.WriteLine("Action Start");
// TODO: how to interact with UI elements?
StartIsEnabled = false;//禁用开始按钮
worker = new Worker();
worker.ProcessAdvanced += Worker_ProcessAdvanced;//工作线程进度事件
worker.WorkComplete += Worker_WorkComplete;//工作线程完成事件
Thread thread = new Thread(worker.Work);
thread.Start(context);//将当前线程同步上下文传递给 worker线程
}
//单击取消工作线程 click cancel action (first thread)
public void ActionCancel()
{
StartIsEnabled = true;//开始按钮可用
worker.Cancel();//取消工作线程
Console.WriteLine("Action Cancel");
}
//与XAML交互的属性 properties to interact with XAML
//UI中start按钮绑定的 启用属性
public bool StartIsEnabled
{
get { return (bool)GetValue(StartIsEnabledProperty); }
set { SetValue(StartIsEnabledProperty, value); }
}
//进度条绑定的 进度属性
public int Progress
{
get { return (int)GetValue(ProgressProperty); }
set { SetValue(ProgressProperty, value * 10); }
}
//工作线程完成 处理函数 event handler (executes in second thread)
private void Worker_WorkComplete(bool cancelled)//UI线程对于工作线程的完成事件处理方法
{
StartIsEnabled = true;
if (cancelled)
Progress = 0;
if (cancelled)
Console.WriteLine("Work cancelled!");
else
Console.WriteLine("Work done.");
}
// event handler (starts from second thread)
private void Worker_ProcessAdvanced(int progress)//UI线程对于工作线程进度更新事件的处理方法
{
Progress = progress + 1; // dirty progressbar delay hack
Progress = progress;
Console.WriteLine("Progress handled " + progress.ToString());
}
}
/// <summary>
/// Slow methods that shoud be started asynchronously
/// 应该异步启动的慢方法
/// </summary>
public class Worker
{
private bool cancelled = false;
public void Work(object param)
{
SynchronizationContext context = (SynchronizationContext) param;
for (int i = 1; i <= 10; i++)
{
if (cancelled)
break;
Console.WriteLine("Working...");
Thread.Sleep(200);
//发送事件进度 send event abount progress 在派生类中重写时,将同步消息分派到同步上下文。
context.Send(OnProgressAdvanced, i);
}
//发送关于已完成工作的事件 send event about work done
context.Send(OnWorkComplete, cancelled);
}
//工作线程的取消方法
public void Cancel()
{
cancelled = true;
Console.WriteLine("Work cancelled!");
}
public event Action<int> ProcessAdvanced;//汇报进度事件
public event Action<bool> WorkComplete; //工作完成事件: bool==true 表示线程被取消。 bool==false 表示线程执行完毕
//工作线程操作封装 用于同步上下文的调用 worker actions wrapper voids for sync.context's call
//通知UI线程 工作线程进度
public void OnProgressAdvanced(object progress)
{
ProcessAdvanced((int)progress);
}
//通知UI线程 工作线程完成
public void OnWorkComplete(object cancelled)
{
WorkComplete((bool) cancelled);
}
}
}