Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.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# 应用程序调用了为不同线程封送的接口。(来自HRESULT的异常:0x8001010E(RPC_E_错误_线程))_C#_Multithreading_Async Await_Windows Phone 8.1 - Fatal编程技术网

C# 应用程序调用了为不同线程封送的接口。(来自HRESULT的异常:0x8001010E(RPC_E_错误_线程))

C# 应用程序调用了为不同线程封送的接口。(来自HRESULT的异常:0x8001010E(RPC_E_错误_线程)),c#,multithreading,async-await,windows-phone-8.1,C#,Multithreading,Async Await,Windows Phone 8.1,在我的WindowsPhone8.1应用程序中,我有一个singleton服务DataService,它应该偶尔下载一些数据。同时在UI上,我应该显示接收到的数据量。用户登录到应用程序时调用DataService.StartGettingData(): void StartGettingData() { if (getDataTaskCancellationTokenSource != null) getDataTaskCancellationTokenSource.Ca

在我的WindowsPhone8.1应用程序中,我有一个singleton服务DataService,它应该偶尔下载一些数据。同时在UI上,我应该显示接收到的数据量。用户登录到应用程序时调用DataService.StartGettingData():

void StartGettingData()
{
    if (getDataTaskCancellationTokenSource != null)
        getDataTaskCancellationTokenSource.Cancel();

    getDataTaskCancellationTokenSource = new CancellationTokenSource();
    var token = getDataTaskCancellationTokenSource.Token;

    Task.Factory.StartNew(async () => await ExecuteCycleAsync(token), token);
}

async Task ExecuteCycleAsync(CancellationToken cancellationToken)
{
    while (true)
    {
        cancellationToken.ThrowIfCancellationRequested();
        await LoadDataAsync(cancellationToken);
        cancellationToken.ThrowIfCancellationRequested();
        await Task.Delay(timeTillNextDownload, cancellationToken);
    }
}
当用户在的帮助下注销时,此任务将被取消

if (getDataTaskCancellationTokenSource != null)
    getDataTaskCancellationTokenSource.Cancel();
包含下载结果的属性如下所示:

List<DataType> Data = new List<DataType>();
public IEnumerable<DataType> Data
{
    get { return Data; }
    set
    {
        Data = value.ToList();
        OnDataUpdated();
    }
}

void OnDataUpdated()
{
    var handler = DataUpdated;
    if (handler != null)
        handler(this, EventArgs.Empty);
}
在xaml中,我将TextBlock绑定到MainViewModel的DataCount属性

int DataCount;
public int DataCount
{
    get { return DataCount; }
    set
    {
        DataCount = value;
        OnPropertyChanged();
    }
}

protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(propertyName));
    }
}
问题就出现在这里:OnPropertyChanged失败于 “应用程序调用了为不同线程封送的接口。(HRESULT的异常:0x8001010E(RPC_E_错误的_线程)),该接口在DataService.LoadDataAsync()中捕获。 我知道运行时试图告诉我我正在从非UI线程访问UI元素。但我是吗?我认为OnPropertyChanged是将UI与其他后台任务断开连接的神奇地方。 当然,问题可以通过以下方式解决:通过实施OnProperty更改:

public CoreDispatcher Dispatcher { get; set; }

protected async void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        });
    }
}

但它真的应该这样实施吗?或者我在DataService.ExecuteCycleAsync()中遗漏了什么?

我不想深入挖掘,我相信您的问题在于:

Task.Factory.StartNew(async () => await ExecuteCycleAsync(token), token);
将其更改为简单的方式,查看其是否按预期工作:

ExecuteCycleAsync(token);
否则,
ExecuteCycleAsync
中的代码在没有同步上下文的线程上开始执行,这可能会导致各种各样的问题,具体取决于
LoadDataAsync
中的内容


注意,像这样调用
ExecuteCycleAsync(token)
仍然是一个fire-and-forget调用,可能没有观察到任何异常(更多)。您可能希望存储它返回的
任务
对象,以便以后能够观察它。

在哪里创建视图模型的新实例,以及它如何连接到xaml?是否在单独的线程中运行取决于调用OnDataUpdate的位置。我怀疑它是在LoadDataAsync方法中,如果是这样,那么是的,它在一个单独的线程中。没有什么魔法可以让UI线程不受影响,从而使您的方法正确。@Kell,OnDataUpdate是在IEnumerable数据中调用的,因此我认为它是在后台线程上运行的。@Tejassarma我的xaml页面的DataContext绑定到ViewModel属性:DataContext=“{Binding ViewModel,RelativeSource={RelativeSource Self}”它的值也是通过Ninject初始化的:ViewModel=NinjectKernel.Get(TypeOfViewModel)
ExecuteCycleAsync(token);