C# WinJS-WinRT组件-应用程序调用为不同线程封送的接口

C# WinJS-WinRT组件-应用程序调用为不同线程封送的接口,c#,windows-8,windows-runtime,winjs,C#,Windows 8,Windows Runtime,Winjs,我正在处理C#中的WinRT组件,我正在从WinJS异步调用它 我正在调用一个库,当调用该库时,抛出应用程序调用的接口,该接口是为不同的线程异常而编组的。我理解这是运行库代码的线程的问题,通过运行JS代码的UI线程 我在这里发现了一些线程,它们提到了可能的工作方式(等等),但这些线程都没有涉及从WinJS调用代码,它们都倾向于XAML 所以,我希望回答两个问题: 在较高的层次上,我应该尝试使WinRT库代码在UI线程上运行吗?从而使它同步?如果这是正确的,那么让我的WinRT代码以这种方式运行(

我正在处理C#中的WinRT组件,我正在从WinJS异步调用它

我正在调用一个库,当调用该库时,抛出
应用程序调用的接口,该接口是为不同的线程
异常而编组的。我理解这是运行库代码的线程的问题,通过运行JS代码的UI线程

我在这里发现了一些线程,它们提到了可能的工作方式(等等),但这些线程都没有涉及从WinJS调用代码,它们都倾向于XAML

所以,我希望回答两个问题:

  • 在较高的层次上,我应该尝试使WinRT库代码在UI线程上运行吗?从而使它同步?如果这是正确的,那么让我的WinRT代码以这种方式运行(下面的代码)最有效的方法是什么
  • RT代码

        public IAsyncOperation<string> ButtonPress()
        {
            return SaveSpreadsheet().AsAsyncOperation();
        }
    
        private async Task<string> SaveSpreadsheet()
        {
            var res = false;
    
            try
            {
                CreateSpreadsheet();
    
                AddSomeContentToASheet();
    
                var folder = KnownFolders.DocumentsLibrary;
                var outFile = await folder.CreateFileAsync("New.xls", CreationCollisionOption.ReplaceExisting);
                res = await book.SaveAsAsync(outFile, ExcelSaveType.SaveAsXLS);
    
                book.Close();
                engine.Dispose();  
            }
            catch (Exception e)
            {
                return e.Message;
            }
    
            return "Success! " + res;
        }
    
    button.onclick = function () {
    
        var rtComponent = new WindowsRuntimeComponent1.Class1();
    
        rtComponent.buttonPress().then(function (res) {
            document.getElementById('res').innerText = "Export should have: " + res;
        });
    };
    
  • 如果1是错误的,我应该尝试使RT代码保持异步,但运行在与JS UI代码相同的线程上,那么我如何获得该线程的引用,然后启动RT代码中的方法?我已经尝试了一些运行RT代码的
    Dispatcher.RunAsync()
    方法,但是当我需要通过WinRT框架方法获取对
    IStorageFile
    的引用时,我就失败了

  • 非常感谢您的任何想法。

    我相信您缺少的是对Task.Run的调用,它实际上创建了一个任务,该任务将在单独的线程上运行操作并进行封送处理

    也就是说,SaveSpreadsheet函数表示它正在返回任务,但实际上并没有在任何地方创建任务,因此只是返回一个字符串。以下是组件中异步函数的一般结构:

    public IAsyncOperation<string> SomeMethodAsync(int id)
    {
        var task = Task.Run<string>(async () =>
        {
            var idString = await GetMyStringAsync(id); 
            return idString;
        });
    
        return task.AsAsyncOperation();
    }
    
    public IAsyncOperation SomeMethodAsync(int-id)
    {
    var task=task.Run(异步()=>
    {
    var idString=await GetMyStringAsync(id);
    返回idString;
    });
    返回任务。AsAsyncOperation();
    }
    
    因此,我认为您只需要更改SaveSpreadsheet以返回字符串(您的代码已经在执行此操作,所以只需将Task更改为String),并使ButtonPress如下所示:

    public IAsyncOperation<string> ButtonPress()
    {
        var task = Task.Run<string>(async () =>
        {
            return await SaveSpreadsheet();
        });
    
        return task.AsAsyncOperation();
    }
    
    public IAsyncOperation按钮按()
    {
    var task=task.Run(异步()=>
    {
    返回等待保存电子表格();
    });
    返回任务。AsAsyncOperation();
    }
    
    顺便说一句,我在MSPress的免费电子书《用HTML、CSS和JavaScript编程Windows应用商店应用程序》第二版的第18章中谈到了这个问题


    另外,如果没有理由让您的组件可以用new实例化,那么您可以将静态键盘添加到ButtonPress(即publicstaticiasyncoperationbuttonpress()),然后使用完全限定的名称WindowsRuntimeComponent1.Class1.ButtonPress()进行调用。然后(…)。这可能会简化您的代码。

    Hi Kraig,感谢您的回答,这确实解决了线程问题。不幸的是,电子表格库仍然不能工作,但这是不相关的!我不认为在您的Win8生态系统之旅中,您遇到过任何可以从WinRT组件、windows应用商店类库或PCL(或任何不是基于XAML的项目)生成电子表格的东西,是吗?不,不幸的是,您没有见过类似的东西。老鼠,非常需要一个!