Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在其他线程中创建UserControl_C#_Wpf - Fatal编程技术网

C# 在其他线程中创建UserControl

C# 在其他线程中创建UserControl,c#,wpf,C#,Wpf,我正在尝试在另一个线程中创建UserControl。我试过1001种方法,但我做不到。我有几个错误,最常见的是:“调用线程必须是STA,因为许多UI组件都需要它。” STA错误,我已经解决了其他类型的问题,例如从另一个线程创建和显示表单,但这不一样,我需要一个方法来返回创建的UserControl。我有类似的东西 private async void SetView<T>() where T : UserControl, new() { // SHOW LOADING

我正在尝试在另一个线程中创建UserControl。我试过1001种方法,但我做不到。我有几个错误,最常见的是:“调用线程必须是STA,因为许多UI组件都需要它。”

STA错误,我已经解决了其他类型的问题,例如从另一个线程创建和显示表单,但这不一样,我需要一个方法来返回创建的UserControl。我有类似的东西

private async void SetView<T>() where T : UserControl, new()
{
    // SHOW LOADING

    CurrentView = await Task.Run(() => new T());

    // HIDE LOADING
}
private async void SetView(),其中T:UserControl,new()
{
//显示加载
CurrentView=wait Task.Run(()=>newt());
//隐藏装载
}

将值从一个线程传递到另一个线程的最简单方法是使用文件。将值序列化为文件,然后对其进行反序列化。因此,您必须使用
System.Windows.Markup.XamlWriter/XamlReader
类将
UserControl
保存到一个文件并将其加载回

下面的示例演示了这一点。您可以使用
System.IO.Path.GetTempFileName()
方法保存到临时文件

<Grid>
    <Button Content="Create on new thread" HorizontalAlignment="Left" Margin="25,25,0,0" VerticalAlignment="Top" Width="126" Click="Button_Click_1"/>
    <Button Content="Deserialize" HorizontalAlignment="Left" Margin="25,63,0,0" VerticalAlignment="Top" Width="126" Click="Button_Click_2"/>
    <Label x:Name="Lbl" Margin="25,127,0,0" VerticalAlignment="Top" Height="105" Width="220"/>        
</Grid>

代码:

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    Task.Factory.StartNew(() => { StartSTATask(create); });
}

bool create()
{
    Button btn = new Button();
    btn.Content = "Press me";

    using (var stream = System.IO.File.Create(@"g:\\button.xaml"))
        System.Windows.Markup.XamlWriter.Save(btn, stream);

    return true;
}

public static Task<bool> StartSTATask(Func<bool> func)
{
    var tcs = new TaskCompletionSource<bool>();
    var thread = new Thread(() =>
    {
        try
        {
            var result = func();
            tcs.SetResult(result);
        }
        catch (Exception e)
        {
            tcs.SetException(e);
        }
    });
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
    return tcs.Task;
}

private void Button_Click_2(object sender, RoutedEventArgs e)
{
    using (var stream = System.IO.File.OpenRead(@"g:\\button.xaml"))
    {
        Button btn = System.Windows.Markup.XamlReader.Load(stream) as Button;
        Lbl.Content = btn;
    }

}
private void按钮\u单击\u 1(对象发送者,路由目标)
{
Task.Factory.StartNew(()=>{StartSTATask(create);});
}
boolcreate()
{
按钮btn=新按钮();
btn.Content=“按我”;
使用(var stream=System.IO.File.Create(@“g:\\button.xaml”))
System.Windows.Markup.XamlWriter.Save(btn,流);
返回true;
}
公共静态任务开始状态任务(Func Func)
{
var tcs=new TaskCompletionSource();
变量线程=新线程(()=>
{
尝试
{
var result=func();
tcs.SetResult(结果);
}
捕获(例外e)
{
tcs.SetException(e);
}
});
SetApartmentState(ApartmentState.STA);
thread.Start();
返回tcs.Task;
}
私有无效按钮\u单击\u 2(对象发送方,路由目标)
{
使用(var stream=System.IO.File.OpenRead(@“g:\\button.xaml”))
{
Button btn=System.Windows.Markup.XamlReader.Load(stream)as按钮;
Lbl.含量=btn;
}
}

见此:。。。此外,当您使用任务时…如果它计划在后台运行…它将使用线程池线程…该线程将使用MTA(多线程单元)进行初始化。一旦初始化到一个特定的单元,它就不能被更改…而且即使可以,您也不想更改它的单元,因为线程池中的线程会被重用。创建控件时花了这么长时间是什么?一个控件通常不需要很长时间来加载。。。控件是否正在加载某种您可以单独加载的数据?