C# 在加载另一个UI线程时更新UI线程
我正在尝试从第一个窗口(GUI_1)创建一个辅助窗口(GUI_2),并在GUI_1初始化时从GUI_2更新一个标签。(类似于加载屏幕) 我试过任务、工厂、调度员,但我认为我缺少了一些东西C# 在加载另一个UI线程时更新UI线程,c#,wpf,multithreading,C#,Wpf,Multithreading,我正在尝试从第一个窗口(GUI_1)创建一个辅助窗口(GUI_2),并在GUI_1初始化时从GUI_2更新一个标签。(类似于加载屏幕) 我试过任务、工厂、调度员,但我认为我缺少了一些东西 public MainWindow() { InitializeComponent(); Task.Factory.StartNew(() => { DispatcherOperation op = Dispatcher.BeginInvoke((Action)(()
public MainWindow()
{
InitializeComponent();
Task.Factory.StartNew(() =>
{
DispatcherOperation op = Dispatcher.BeginInvoke((Action)(() => {
Window1 gui = new Window1();
gui.Show();
}));
});
}
这样,我的GUI_2就打开了,但是如果我试图更新标签,它只会显示最后一个值。(即:a表示线程的i=0到10。仅显示10值)
我怎样才能做到这一点
编辑:
我尝试过以下代码:
public partial class Loading : Window
{
public static object uiContext;
private List<string> paths;
private List<Color> colors;
public Loading(List<string> _paths, List<Color> _colors)
{
InitializeComponent();
paths = _paths;
colors = _colors;
}
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
Storyboard s = (Storyboard)TryFindResource("sb");
s.Begin(); // Start animation
await Task.Run(() => EXCEL.Analogize(paths, this, colors));
Close();
}
public void UpdateWindow(string text, int percent)
{
Dispatcher.Invoke(() =>
{
progress_label.Content = text;
progress.Value = percent;
});
}
}
公共部分类加载:窗口
{
公共静态对象上下文;
私有列表路径;
私有列表颜色;
公共加载(列表路径、列表颜色)
{
初始化组件();
路径=_路径;
颜色=_颜色;
}
已加载专用异步无效窗口(对象发送方,RoutedEventArgs e)
{
故事板s=(故事板)TryFindResource(“sb”);
s、 Begin();//开始动画
等待任务。运行(()=>EXCEL.Analogize(路径、此、颜色));
Close();
}
public void UpdateWindow(字符串文本,整数百分比)
{
Dispatcher.Invoke(()=>
{
进度\标签内容=文本;
进度值=百分比;
});
}
}
在我的EXCEL.Analogize中,我使用gui_loading.UpdateWindow(文本,百分比)
它正在工作,但如果我尝试对windows类执行相同的操作,它将不再更新。可能在GUI_2 UI任务中忙于加载,并且仅在完成时显示。尝试将更新放在其他任务上,并将其与UI同步 在GUI_2中 编辑:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
_SyncContext = SynchronizationContext.Current;
UpdateLabel();
}
SynchronizationContext _SyncContext = null;
private async void UpdateLabel()
{
await Task.Run(() =>
{
for (int i = 1; i < 11; i++)
{
Load(i);
Thread.Sleep(1000);
}
});
}
private void Load(int i)
{
SendOrPostCallback updateUI = new SendOrPostCallback(arg =>
{
yourLabelName.Content = $"{i}/10";
});
_SyncContext.Send(updateUI, null);
}
}
这个我测试过,它对我有效
编辑2
是的,这是可能的
一种方法是直接在构造函数中传递参数
如Window1(字符串文本)代码>调用该窗口时,传递参数Window1(text)代码>
第二种方法是(我更喜欢这种方法)创建接口(类似IWindow的东西)并在其中放入简单的加载方法
像这样
public interface IWindow
{
void Load(string text);
}
public partial class Window1 : Window , IWindow
{
//here you implement Load(string text) method.
然后你通过一些DI传递IWindow im主窗口构造函数来解析它(Autofac,Unity)
在主窗口中,您可以实例化如下内容:
//主窗口构造函数
MainWindow(IWindow iWindow)
{
_iWindow = iWindow;
}
public IWindow _iWindow { get; private set; }
并在主窗口中具有Load()方法
public void Load()
{
_iWindow.Load(textToPassAsParameter);
//this will call Load method from Window1
}
private bool _isBusy;
public bool IsBusy
{
get { return _isBusy; }
set
{
if (_isBusy != value)
{
_isBusy = value;
OnPropertyChanged();
}
}
}
要调用该加载方法,可以在xaml中进行
添加名称空间
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions">
并从MainWindo调用Load方法(将从Window1调用Load)
包围
<extToolkit:BusyIndicator Grid.Row="1"
BusyContent="Loading..."
IsBusy="{Binding IsBusy}">
<!-- your loading area -->
在加载方法中更新该get
private void Load()
{
IsBusy = true;
// some load logic
//{
// IsBusy=false;
//}
}
然后在MainWindow构造函数中调用该加载方法。这样,您就不需要Window1,因为该工具包将作为子工具放置在主窗口中,并作为进度条工作。
其中,如果您在BusyContent=“这是xceed进度条…”
中写入,您将像这样从xceed获得子加载窗口。考虑只使用一个窗口,您可以将加载屏幕显示为主窗口根网格的子级。您尝试过但不起作用的代码是什么?我在第一个主题中尝试了一篇帖子,或者在第二个GUI的方法中放置dispatcher.invoke。为什么我会获得否决票?我尝试过,但windows只有在计数结束后才完成加载。sry,尚未测试它。现在我进行了测试,就像你说的,所以我做了一些修改,在这种情况下效果很好。window1.xaml只是一个显示用途的标签。像这样,我做了线。睡眠(1000)因为它运行到10这么快,这只是为了让它显示它如何计数。这几乎是我喜欢的!计数器在windows1中,是否可以从第一个窗口使用gui.UpdateLabel(“文本”)之类的内容进行更新?我有两种更新方法,可以传递参数。我不确定它是否足够清晰,但用简单的代码解释这个主题并不容易。我尽我所能把它说清楚。
<extToolkit:BusyIndicator Grid.Row="1"
BusyContent="Loading..."
IsBusy="{Binding IsBusy}">
<!-- your loading area -->
private bool _isBusy;
public bool IsBusy
{
get { return _isBusy; }
set
{
if (_isBusy != value)
{
_isBusy = value;
OnPropertyChanged();
}
}
}
private void Load()
{
IsBusy = true;
// some load logic
//{
// IsBusy=false;
//}
}