首页 > 解决方案 > uwp - '应用程序调用了一个为不同线程编组的接口

问题描述

我正在尝试使用 MVVM 创建 UWP 聊天。我不断收到此错误:

应用程序调用了为不同线程编组的接口

在我的视图模型中:

public void Notify(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

每次将值设置为绑定到 xaml 中的 TextBlock.Text 属性的字符串属性时,都会发生此函数;

我尝试在视图模型中插入 TextBlock(vm 绑定到其文本属性)并删除 xaml 中的所有绑定并使用此函数:

private async Task LoadMessage(string sender, string message)
    {
        await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            ChatBox += $"{sender}: {message} \n";
        });
    }

还是一样,只是现在在上面的函数中抛出了异常。

我在搜索答案时找到了另一个调度程序,但似乎 uwp 无法识别它并用红色下划线标记它:

await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            //my code           
        });

我试过了 :

await CoreDispatcher.RunAsync(CoreDispatcherPriority.Normal, () => 
        {
            ChatBox += $"{sender}: {message} \n";
        });

但后来我得到了

非静态字段、方法需要对象引用

所以我创建了一个静态类来保存这个函数:

public static void UpdateTextBlock(TextBlock textBlock, string sender, string message)
    {

        textBlock.Text = $"{sender}: {message}";
    }

并将其插入此调度程序。还是不行。仍然:需要对象引用...

我真的希望它是 MVVM,但任何可行的解决方案都是一种祝福。

编辑

今天我尝试回到绑定和 mvvm 模式。我将 LoadMessage 函数包装在这样的任务中:

private async Task<bool> LoadMessage(string sender, string message)
    {
        bool flag = false;
        await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            TextBindingProperty += $"{sender}: {message} \n";
            flag = true;
        });

        return flag;
    }

_hubProxy.On<string, string>("SendMessage", async (sender, message) =>
        {
            var result = await Task.Run(() => LoadMessage(sender, message));
        });

仅在类中存在相同的异常:MyView.g.cs

在这种方法中:

public static void Set_Windows_UI_Xaml_Controls_TextBlock_Text(global::Windows.UI.Xaml.Controls.TextBlock obj, global::System.String value, string targetNullValue)
        {
            if (value == null && targetNullValue != null)
            {
                value = targetNullValue;
            }
            obj.Text = value ?? global::System.String.Empty; //in this line!!!
        }
    };

我的视图模型实现 INotifyPropertyChanged

 public class UserViewModel : INotifyPropertyChanged
{
private string chatBox;

    public string ChatBox
    {
        get { return chatBox; }
        set { chatBox = value; Notify(nameof(ChatBox)); }
    }

 public event PropertyChangedEventHandler PropertyChanged;

    public void Notify(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

绑定到此属性的 xaml 元素如下所示:

 <TextBlock Name="chatTbl"  Text="{x:Bind userViewModel.ChatBox, Mode=TwoWay}" />

标签: c#multithreadingmvvmbindinguwp

解决方案


解决方案:

所以努力让聊天工作这就是问题所在:

await CoreApplication.MainView

由于聊天与主页位于不同的视图中,因此找不到绑定或 xaml 元素。

我的朋友意识到,为了在其他视图中进行更改,您需要获取其对象,因此,我们将此属性添加到视图模型中:

  public CoreApplicationView CurrentView { get; set; }

启动聊天室视图时,我们设置属性:

public UserViewModel userViewModel;
    public ChatRoom(UserViewModel userViewModel)
    {
        this.InitializeComponent();
        this.userViewModel = userViewModel;
        userViewModel.ChatTbl = chatTbl;


        userViewModel.CurrentView = CoreApplication.GetCurrentView();//this line

    }

现在,当我们需要在我们使用的视图中进行更改时:

 _hubProxy.On<string, string>("SendMessage", async (sender, message) =>
        {

            await CurrentView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                ChatTbl.Text += $"{sender}: {message} \n";
            });
        });

所以与其await CoreApplication.MainView

利用await CurrentView.CoreWindow

希望这会帮助我知道它会帮助我的人


推荐阅读