titans
titans

Reputation: 79

c# winrt error 0x8001010E

I've made a program that creates a thread and in that thread create image:

private async void GetCamera()
{
   ....
    tk = new Task(MyAwesomeTask);
    tk.Start();

}

private async void MyAwesomeTask()
{
        while (true)
        {
            await Task.Delay(TimeSpan.FromSeconds(0.5));
            SavePhoto1();
        }
}

private  void SavePhoto1()
{
        try
        {
            WriteableBitmap wb1 = new WriteableBitmap(320, 240);//throw exception
        }catch (Exception ee)
        {
            String s = ee.ToString();
        }

}

But line

WriteableBitmap wb1 = new WriteableBitmap(320, 240); 

throws exception:

s="System.Exception: The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))\r\n at Windows.UI.Xaml.Media.Imaging.WriteableBitmap..ctor(Int32 pixelWidth, Int32 pixelHeight)\r\n at TestVideo.MainPage.SetImageFromStream() in ...\MainPage.xaml.cs:line 500\r\n at TestVideo.MainPage.SavePhoto1() in ....\MainPage.xaml.cs:line 145"

What I need to do?

Upvotes: 1

Views: 1476

Answers (1)

chue x
chue x

Reputation: 18803

The first problem is that you are using async void. The only time that you should do this is when the method is an event handler. In your case, you should use async Task instead:

private async Task GetCamera()
{
   ....
    //tk = new Task(MyAwesomeTask);
    //tk.Start();
    await Task.Run(async () => await MyAwesomeTask());
    ...    
}

private async Task MyAwesomeTask()
{
    while (true)
    {
        await Task.Delay(TimeSpan.FromSeconds(0.5));
        // added await
        await SavePhoto1();
    }
}

You do not actually need to return a Task in the above methods. The compiler automagically does that for you.

To address your question, you should only create WriteableBitmap objects on the UI thread. You can do so with this:

private async Task SavePhoto1()
{
    try
    {
        WriteableBitmap wb1 = null;
        await ExecuteOnUIThread(() =>
        {
            wb1 = new WriteableBitmap(320, 240);//throw exception
        });

        // do something with wb1 here
        wb1.DoSomething();
    }catch (Exception ee)
    {
        String s = ee.ToString();
    }
}    

public static IAsyncAction ExecuteOnUIThread(Windows.UI.Core.DispatchedHandler action)
{
    return Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, action);
}

I didn't test the above by compiling it, but it should give you a good start. Let me know if you have questions.

Upvotes: 4

Related Questions