Exception thrown when use await Task.Run() in UWP

-2

I used two Task.Run. In the first one everything works correctly, but in the second an exception is thrown:

Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD).

I do not understand how to solve it. I would like to understand from the code that the Task.Run returns a TextHighlighter. What is the right solution?

xaml:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid x:Name="CommandGrid" Margin="25,50,0,50" Width="200" HorizontalAlignment="Left">
        <StackPanel x:Name="CommandStack" Orientation="Vertical">
            <Button x:Name="btnFind" Click="btnFind_Click" Content="Find Words" HorizontalAlignment="Stretch" Height="32"/>
            <TextBox x:Name="txbToFind" HorizontalAlignment="Stretch" Height="32" Margin="0,20,0,0"/>
        </StackPanel>
    </Grid>
    <Grid x:Name="BaseGrid" Margin="250,50,50,50" Background="#FFCBF3A6">
        <ScrollViewer x:Name="BaseScroll">
            <RichTextBlock x:Name="TextOneRich" Margin="20,20,35,20"/>
        </ScrollViewer>
    </Grid>
</Grid>

xaml.cs:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        Paragraph paragraph = new Paragraph();
        paragraph.Inlines.Add(new Run() { Text = "Paste the text here" });
        TextOneRich.Blocks.Add(paragraph);
    }

    private async void btnFind_Click(object sender, RoutedEventArgs e)
    {
        string tofind = txbToFind.Text.ToLower();
        string completeText = string.Empty;

        for (int a = 0; a <= TextOneRich.Blocks.Count - 1; a++)
        {
            Paragraph paragraphCurrent = TextOneRich.Blocks[a] as Paragraph;
            for (int b = 0; b <= paragraphCurrent.Inlines.Count - 1; b++)
            {
                completeText += (paragraphCurrent.Inlines[b] as Run).Text;
            }
        }

        List<int> indexList = await Task.Run(async () => await DoStuffAsync(completeText, tofind)); // Works well
        TextHighlighter HighlighterAll = await Task.Run(async () => await CreateHighlighter(indexList, tofind.Length)); // Generate exception

        TextOneRich.TextHighlighters.Clear();
        TextOneRich.TextHighlighters.Add(HighlighterAll);
    }

    private async Task<TextHighlighter> CreateHighlighter(List<int> listaindex, int lenght)
    {
        TextHighlighter Higlighter = new TextHighlighter() { Foreground = new SolidColorBrush(Colors.White), Background = new SolidColorBrush(Color.FromArgb(255, 7, 58, 77)) };
        for (int a = 0; a <= listaindex.Count - 1; a++)
        {
            Higlighter.Ranges.Add(new TextRange() { StartIndex = listaindex[a], Length = lenght });
        }
        return await Task.FromResult(Higlighter);
    }

    private async Task<List<int>> DoStuffAsync(string myTxt, string toFind)
    {
        bool thereis = true;
        List<int> indexList = new List<int>();
        string remainingText = string.Empty;
        remainingText = myTxt;
        int progressiveIndex = 0;
        int index = 0;
        while (thereis)
        {
            if (remainingText.ToLower().IndexOf(toFind) != -1)
            {
                indexList.Add(remainingText.ToLower().IndexOf(toFind) + progressiveIndex);
                index = remainingText.ToLower().IndexOf(toFind) + 1;
                progressiveIndex += index;
                remainingText = remainingText.Substring(index, remainingText.Length - index);
            }
            else
            {
                thereis = false;
            }
        }
        return await Task.FromResult(indexList);
    }
}

Text to paste: text.

Exception screenshot: exception.

Thanks for your help.

c#
uwp
task
asked on Stack Overflow Jan 31, 2018 by Jib58 • edited Jan 31, 2018 by Parsa Karami

1 Answer

0

The general problem with your code is that you are using Tasks for code that performs no kind of asynchronous I/O work. Both CreateHighlighter and DoStuffAsync are said to be Task for absolutely no good reason.
Moreover, since CreateHighlighter is working with UI objects, is worse to make that async since you aren't in the UI context (due to your usage of Task.Run). This is how your code should look like:

public sealed partial class MainPage : Page
{
    ... 
    private async void btnFind_Click(object sender, RoutedEventArgs e)
    {
        ...
        List<int> indexList = await Task.Run(DoStuff(completeText, tofind)); 
        TextHighlighter HighlighterAll = CreateHighlighter(indexList, tofind.Length);
        ...
    }

    private TextHighlighter CreateHighlighter(List<int> listaindex, int lenght)
    {
        ...
        return Higlighter;
    }

    private List<int> DoStuff(string myTxt, string toFind)
    {
        ...
        return indexList;
    }
}
answered on Stack Overflow Jan 31, 2018 by Camilo Terevinto

User contributions licensed under CC BY-SA 3.0