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.
The general problem with your code is that you are using Task
s 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;
}
}
User contributions licensed under CC BY-SA 3.0