草庐IT

c# - 在多窗口 UWP 应用程序中引发和处理事件

coder 2024-06-12 原文

我创建了一些测试代码,以便尝试弄清楚如何在 UWP 中正确使用多个窗口。我想看看我是否可以触发一个事件并让多个窗口在事件处理程序中更新它们的 UI。我终于得到了一些东西,但我不完全确定它为什么起作用。

这是在我的页面中创建的类<​​>

public class NumberCruncher
{
    private static Dictionary<int, Tuple<CoreDispatcher, NumberCruncher>> StaticDispatchers { get; set; }

    static NumberCruncher()
    {
        StaticDispatchers = new Dictionary<int, Tuple<CoreDispatcher, NumberCruncher>>();
    }

    public NumberCruncher()
    {
    }

    public event EventHandler<NumberEventArgs> NumberEvent;

    public static void Register(int id, CoreDispatcher dispatcher, NumberCruncher numberCruncher)
    {
        StaticDispatchers.Add(id, new Tuple<CoreDispatcher, NumberCruncher>(dispatcher, numberCruncher));
    }

    public async Task SendInNumber(int id, int value)
    {
        foreach (var dispatcher in StaticDispatchers)
        {
            await dispatcher.Value.Item1.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                Debug.WriteLine($"invoking {dispatcher.Key}");
                dispatcher.Value.Item2.NumberEvent?.Invoke(null, new NumberEventArgs(id, value));
            });
        }
    }
}

这是我的 MainPage 代码的相关部分

    NumberCruncher numberCruncher;

    public MainPage()
    {
        this.InitializeComponent();
        numberCruncher = new NumberCruncher();
        numberCruncher.NumberEvent += NumberCruncher_NumberEvent;
    }

    private async void NumberCruncher_NumberEvent(object sender, NumberEventArgs e)
    {
        listView.Items.Add($"{e.Id} sent {e.Number}");
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        NumberCruncher.Register(ApplicationView.GetForCurrentView().Id, Window.Current.Dispatcher, numberCruncher);
    }

我有一个按钮可以创建 MainPage 的新 View 。然后我有另一个调用 SendInNumber() 方法的按钮。

当我导航到 MainPage 时,我为窗口和 NumberCruncher 实例注册了 Dispatcher。然后,在触发事件时,我为特定的 Dispatcher 使用 NumberCruncher EventHandler。

这不会抛出编码(marshal)处理异常。如果我尝试使用当前类的 EventHandler

await dispatcher.Value.Item1.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            Debug.WriteLine($"invoking {dispatcher.Key}");
            NumberEvent?.Invoke(null, new NumberEventArgs(id, value));
        });

尝试将项目添加到 listView 时出现编码异常。但是,如果我在 MainPage 中维护 SynchronizationContext,然后使用 SynchronizationContext.Post 更新 listView。效果不错

    SynchronizationContext synchronizationContext;

    public MainPage()
    {
        this.InitializeComponent();
        numberCruncher = new NumberCruncher();
        numberCruncher.NumberEvent += NumberCruncher_NumberEvent;
        synchronizationContext = SynchronizationContext.Current;
    }

    private async void NumberCruncher_NumberEvent(object sender, NumberEventArgs e)
    {
        synchronizationContext.Post(_ =>
        {
            listView.Items.Add($"{e.Id} sent {e.Number}");
        }, null);
    }

然而,这不起作用,并在尝试更新 listView 时抛出编码异常。

private async void NumberCruncher_NumberEvent(object sender, NumberEventArgs e)
    {
        await CoreApplication.GetCurrentView().CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            listView.Items.Add($"{e.Id} sent {e.Number}");
        });
    }

这是怎么回事?

最佳答案

要记住的重要一点是,当触发事件时,订阅的方法将在与 Invoke 方法相同的线程上被调用。

If I try to use the current class's EventHandler, I get a marshaling exception when trying to add the item to the listView.

第一个错误的发生是因为您试图在另一个窗口的调度程序 (dispatcher.Value.Item1) 上触发当前类的事件。假设事件发生在 Window 1 上,dispatcher.Value.Item1 属于 Window 2。一旦进入 Dispatcher block ,您就是 Window 2 的 UI 线程并触发 Window 1NumberEvent NumberCruncher 将在Window 2 UI 线程上运行Window 1 处理程序,这会导致异常。

However this does not work and throws a marshaling exception when trying to update listView.

GetCurrentView() 方法返回当前事件的 View 。因此,无论哪个应用程序 View 在那一刻处于事件状态,都将被返回。在您的情况下,它将是您单击按钮的那个。如果您在目标窗口的 UI 线程上调用 Invoke 方法,则不需要在 NumberEvent 处理程序中添加任何其他代码。

关于c# - 在多窗口 UWP 应用程序中引发和处理事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48126851/

有关c# - 在多窗口 UWP 应用程序中引发和处理事件的更多相关文章

  1. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  2. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  3. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  4. ruby-on-rails - Capybara-webkit 引发 Capybara::Driver::Webkit::WebkitInvalidResponseError - 2

    我在rspec中收到来自webkit驱动程序的以下消息:Capybara::Driver::Webkit::WebkitInvalidResponseError:UnabletoloadURL:http://127.0.0.1:44923/posts几天前它成功了。问题出在save_page方法上。有什么问题吗? 最佳答案 当我的页面出现错误时,我收到过类似的错误消息。您应该通过在测试模式下启动服务器(railss-etest)并自行访问页面来手动检查情况是否如此。 关于ruby-on-

  5. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  6. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  7. ruby-on-rails - 事件记录 : Select max of limit - 2

    我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).

  8. ruby - (Ruby || Python) 窗口管理器 - 2

    我想用这两种语言中的任何一种(最好是ruby​​)制作一个窗口管理器。老实说,除了我需要加载某种X模块外,我不知道从哪里开始。因此,如果有人有线索,如果您能指出正确的方向,那就太好了。谢谢 最佳答案 XCB,X的下一代API使用XML格式定义X协议(protocol),并使用脚本生成特定语言绑定(bind)。它在概念上与SWIG类似,只是它描述的不是CAPI,而是X协议(protocol)。目前,C和Python存在绑定(bind)。理论上,Ruby端口只是编写一个从XML协议(protocol)定义语言到Ruby的翻译器的问题。生

  9. ruby-on-rails - 事件管理员和自定义方法 - 2

    这是我在ActiveAdmin中的自定义页面ActiveAdmin.register_page"Settings"doaction_itemdolink_to('Importprojects','settings/importprojects')endcontentdopara"Text"endcontrollerdodefimportprojectssystem"rakedataspider:import_projects_ninja"para"OK"endendend我想做的是,当我单击“导入项目”按钮时,我想在Controller中执行rake任务。但是我无法访问该方法。可能是什

  10. Ruby-vips 图像处理库。有什么好的使用示例吗? - 2

    我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby​​代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby​​-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby​​-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby​​-vips的github页面上的链接,我们将不胜感激!如果有ruby​​-

随机推荐