C# - WPF - 从另一个线程上的另一个 class 更新 UI
C# - WPF - Updating the UI from another class on another Thread
我浏览了互联网并找到了一个很好的解决方案,我将其合并到下面的代码中,但是它并不能完全满足我的要求,它只在调用更新时有效,但我想 运行 另一个 class 中的一个方法,然后让该方法调用将向 UI 报告的方法,并仅传递一些信息,因此该模型只是在操作之前更改按钮内容 运行.
使用 Dispatcher,我可以获得 UI 控件进行更新,但是我不只是想这样做,我想执行一些功能然后进行 UI 更新。
所以可能有一些我没有得到的理论,我知道 Invoke 是一个同步操作并且突破了它所做的代码 运行 但是 UI 没有更新。
主窗口
有一个内容为“点击我”
的按钮
代码隐藏
public partial class MainWindow : Window
{
public static Button windowButton;
public MainWindow()
{
InitializeComponent();
windowButton = btnStart;
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
// Run a Process in another class on a different Thread
ProcessClass processClass = new ProcessClass();
Task processTask = new Task(() =>
{
processClass.DoSomething();
});
processTask.Start();
}
}
}
ProcessClass
class ProcessClass:MainWindow
{
public static void UpdateUI()
{
App.Current.Dispatcher.Invoke(delegate
{
windowButton.Content = "CHANGED CONTENT";
});
}
public void DoSomething()
{
UpdateUI();
int counter = 0;
for(int i = 1; i < 100; i++)
{
counter += i;
Thread.Sleep(100);
}
MessageBox.Show($"Task Completed, answer is {counter}");
}
}
假设Process Class是您自己可以更新的代码,将DoDomething()
的签名更改为
public async Task DoSomething(IProgress<string> progress)
{
progress.Report("Begin DoSomething()");
var counter = 0;
for(var i = 1; i < 100; i++)
{
counter += i;
await Task.Delay(100).ConfigureAwait(false);
progress.Report($"DoSomething() - i = {i}");
}
progress.Report($"DoSomething() Completed, answer is {counter}");
}
现在可以编写按钮单击处理程序
private async void btnStart_Click(object sender, RoutedEventArgs e)
{
// usually you would update some other control such as a TextBlock
// for the feedback, rather than the button content
var progress = new Progress<string>(s => btnStart.Content = s);
ProcessClass processClass = new ProcessClass();
await processClass.DoSomething(progress).ConfigureAwait(false);
}
我浏览了互联网并找到了一个很好的解决方案,我将其合并到下面的代码中,但是它并不能完全满足我的要求,它只在调用更新时有效,但我想 运行 另一个 class 中的一个方法,然后让该方法调用将向 UI 报告的方法,并仅传递一些信息,因此该模型只是在操作之前更改按钮内容 运行.
使用 Dispatcher,我可以获得 UI 控件进行更新,但是我不只是想这样做,我想执行一些功能然后进行 UI 更新。 所以可能有一些我没有得到的理论,我知道 Invoke 是一个同步操作并且突破了它所做的代码 运行 但是 UI 没有更新。
主窗口 有一个内容为“点击我”
的按钮代码隐藏
public partial class MainWindow : Window
{
public static Button windowButton;
public MainWindow()
{
InitializeComponent();
windowButton = btnStart;
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
// Run a Process in another class on a different Thread
ProcessClass processClass = new ProcessClass();
Task processTask = new Task(() =>
{
processClass.DoSomething();
});
processTask.Start();
}
}
}
ProcessClass
class ProcessClass:MainWindow
{
public static void UpdateUI()
{
App.Current.Dispatcher.Invoke(delegate
{
windowButton.Content = "CHANGED CONTENT";
});
}
public void DoSomething()
{
UpdateUI();
int counter = 0;
for(int i = 1; i < 100; i++)
{
counter += i;
Thread.Sleep(100);
}
MessageBox.Show($"Task Completed, answer is {counter}");
}
}
假设Process Class是您自己可以更新的代码,将DoDomething()
的签名更改为
public async Task DoSomething(IProgress<string> progress)
{
progress.Report("Begin DoSomething()");
var counter = 0;
for(var i = 1; i < 100; i++)
{
counter += i;
await Task.Delay(100).ConfigureAwait(false);
progress.Report($"DoSomething() - i = {i}");
}
progress.Report($"DoSomething() Completed, answer is {counter}");
}
现在可以编写按钮单击处理程序
private async void btnStart_Click(object sender, RoutedEventArgs e)
{
// usually you would update some other control such as a TextBlock
// for the feedback, rather than the button content
var progress = new Progress<string>(s => btnStart.Content = s);
ProcessClass processClass = new ProcessClass();
await processClass.DoSomething(progress).ConfigureAwait(false);
}