Ошибка, создав новый элемент - WPF Async/Await

Выполнив мой код я получаю следующую ошибку:

System. InvalidOperationException' in PresentationCore.dll

The calling thread must be STA, because many UI components require this

Они могли бы помогать мне исправлять мой код?

Упрощенный код WPF:

void CrearBtnNews()
{
    KinectTileButton botontest = new KinectTileButton
    {
        Style = FindResource("KinectTileButtonStyle1") as Style,
        Content = "WeB",
        Height = 265,
        Width = 450,
        Background = null,
        BorderBrush = null
    };
    botontest.Click +=
    async (o, args) =>
    {
        await Task.Run(()=> BrowserAsync());

    };
}
private void BrowserAsync()
{
    Grid gridx = new Grid();////// el ERROR ocurre en esta linea ///
    System.Threading.Thread.Sleep(8000);
        MessageBox.Show("working 8 seg");

}
2
задан 14.01.2017, 20:44
0 ответов

Что ошибка старается говорить тебе, дело в том, что он незаконный, создавать или манипулировать визуальным контролем (как Grid) в thread (трэде), который не был бы thread интерфейса.

В этом случае, проблема - что Task.Run() выполни метод BrowserAsync в различном трэде, поскольку ты не можешь, ты был бы должен даже не создавать один Grid там. В самом деле, также ты не был бы должен выполнять один MessageBox.Show() там. Главным образом, ты ничего не можешь делать в этом методе, который завертывает действия интерфейса.

Трудно предлагать тебе решение, приведенное в соответствие вне того, чтобы говорить тебе, что ты не можешь делать это, потому что очевидно, что твой код одинокий доказательство и ничего не делает пока.

Но если намерение состоит в том, чтобы выполнять длинную работу в методе BrowserAsync в различном трэде для того, чтобы интерфейс не tranque, это хорошо. Но ты будешь должен ограничиваться тем, чтобы сделать и накапливать результат этой работы используя какую-то структуру, которая не была бы контролем интерфейса, и потом возвращать этот результат главному thread интерфейса, где там да, ты сможешь использовать этот результат, чтобы делать изменения в контроль интерфейса.

Например, налаживая твою ситуацию немножко, давайте говорить, что, кликнув кнопки, то, что ты хочешь сделать, является длинным вычислением, результат которого ты хочешь распределить textbox.

Сходный с твоим кодом, мы могли пробовать делать следующее:

botontest.Click += 
    async (src, args) =>
    {
        await Task.Run(() => CalculoLargo());
    };

private void CalculoLargo() {
    Thread.Sleep(30000); // simulando un cálculo largo
    int resultado = 100;
    textbox1.Text = $"Resultado del cálculo: {resultado}"; // error!!
}

Но решение, которое пробует распределить результат textbox, не является законным по уже упомянутым причинам.

Скорее, правильный способ осуществлять вычисление в отличном трэде и потом распределять результат textbox таким образом:

botontest.Click += 
    async (src, args) =>
    {
        int resultado = await Task.Run(() => CalculoLargo());
        textbox1.Text = $"Resultado del cálculo: {resultado}";
    };

private int CalculoLargo() {
    Thread.Sleep(30000); // simulando un cálculo largo
    return 100;
}

Поскольку ты можешь замечать, дорогая часть еще осуществляет в отличном трэде для не trancar трэд интерфейса. Но в момент того, чтобы быть должным распределять результат в визуальный контроль (textbox), нужно делать это в трэде интерфейса. В этом примере, этого добиваются делая эту часть после await Task.Run(), когда код там да выполнен в трэде интерфейса.

Я надеюсь, что этот пример оставляет тебе модель, от как ты можешь добиваться твоей цели, не получая ошибки.

2
ответ дан 03.12.2019, 17:40
  • 1
    Привет. Спасибо за responder.¿ Невозможно тогда строить UI в параллельном трэде?.¿ Как могла бы грузить веб-страница, не соединяя интерфейса?.Muchas Спасибо снова. –  14.01.2017, 21:51
  • 2
    ¿ Строить UI в параллельном трэде? Окончательно ты не можешь делать это. Операции UI должны осуществляться в главном трэде интерфейса. Нет другой. ¿ Как могла бы грузить веб-страница, не соединяя интерфейса? Allí введи пример, который я дал тебе. Идея состоит в том, что ты можешь отделять работу в 2 частях: 1) загружать контент pá gina Веб в переменной string возможно (это sí ты это можешь заставлять в параллельном трэде 2) распределять контент переменной в твои компоненты интерфейса (это должно делаться в главном трэде)... (продолженный) –  14.01.2017, 21:58
  • 3
    Обычно, первая часть - дорогая, но эта sí ты можешь делать в параллельном трэде. Но ты diré что в действительности, вероятно даже ты не нуждаешься в параллельном трэде, чтобы делать то, что ты хочешь. В зависимости от librerí которого ты используешь, чтобы загружать pá gina Веб, возможно, что уже он включает mé каждый async, которому тебя может делать его await без необходимости делать один Task.Run(). Но я не могу говорить тебе, не зная того, что está s используя. –  14.01.2017, 22:01
  • 4
    Я использую книжные магазины cefsharp. это верно, не блокирует интерфейс. В действительности была testeando тема async/await для будущих использований. Спасибо за твою помощь –  14.01.2017, 22:17
  • 5
    Только как acotació n, если ты можешь создавать элементы UI в чередующихся трэдах, но если ты хочешь применить их, или algú n способ работать с тогда реальной UI, если ты должен делать это прямо на главном трэде, ты можешь делать это в travé s dispatcher. –  20.01.2017, 04:18

Теги

Похожие вопросы