AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 77033849
Accepted
sdbbs
sdbbs
Asked: 2023-09-04 03:22:39 +0800 CST2023-09-04 03:22:39 +0800 CST 2023-09-04 03:22:39 +0800 CST

É possível iniciar e aguardar PerformClick de um componente de formulário de outro componente?

  • 772

Estou tendo muita dificuldade em descobrir se é possível realizar um clique virtual em um elemento de formulário C# de outro elemento e aguardar a conclusão antes de continuar.

Por exemplo (infelizmente incompleto), o que estou tentando fazer é o seguinte

  private async void btn_my_Click(object sender, EventArgs e)
  {
      await Task.Run(() => radio_button_special.PerformClick()); // https://stackoverflow.com/q/14024963

      // once this is done, proceed with rest of processing
      do_rest_of_processing();
  }

Quando clico no botão na execução de depuração, o VS2019 quebra com "InvalidOperationException: operação entre threads inválida: controle 'radio_button_special' acessado de um thread diferente do thread em que foi criado."

No entanto, se eu apenas executar o exe fora da depuração do Visual Studio, o botão parece funcionar (ou seja, posso ver no aplicativo que radio_button_special.PerformClick() é concluído primeiro e do_rest_of_processing() é executado depois - e não recebo uma exceção explícita funcionando assim, então parece funcionar como eu imaginei).

Mas essa exceção me assusta, então gostaria de me livrar dela - e tentei remediar assim, que tentei construir a partir de outros trechos no SO:

  private async void btn_my_Click(object sender, EventArgs e)
  {
      // first, I want to call the function otherwise called
      // when the radio button is clicked, and wait for it to complete
      radio_button_special.Invoke((MethodInvoker)async delegate
      {
          await Task.Run(() => radio_button_special.PerformClick()); // https://stackoverflow.com/q/14024963
      });
      // once this is done, proceed with rest of processing
      do_rest_of_processing();
  }

Agora, essa função já dá um aviso na IDE do VS2019:

aviso CS1998: Este método assíncrono não possui operadores 'await' e será executado de forma síncrona. Considere usar o operador 'await' para aguardar chamadas de API sem bloqueio ou 'await Task.Run(...)' para realizar trabalho vinculado à CPU em um thread em segundo plano.

... e se eu depurar, execute o exemplo, recebo o rastreamento de pilha:

System.Reflection.TargetInvocationException
  HResult=0x80131604
  Message=Exception has been thrown by the target of an invocation.
  Source=mscorlib
  StackTrace:
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   ...
   at System.Windows.Forms.Application.Run(Form mainForm)
   at my_test.Program.Main() in D:\work\bbs\BBS_DEV\BAPS_git\my_test\Program.cs:line 28

  This exception was originally thrown at this call stack:
    System.Windows.Forms.Control.Handle.get()
    System.Windows.Forms.Control.InternalHandle.get()
    System.Windows.Forms.Control.Update()
    System.Windows.Forms.ButtonBase.ResetFlagsandPaint()
    System.Windows.Forms.RadioButton.PerformClick()
    my_test.main_form.btn_my_Click.AnonymousMethod__122_1() in main_form.cs
    System.Threading.Tasks.Task.InnerInvoke()
    System.Threading.Tasks.Task.Execute()
    System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)
    ...
    [Call Stack Truncated]

Inner Exception 1:
InvalidOperationException: Cross-thread operation not valid: Control 'radio_button_special' accessed from a thread other than the thread it was created on.

Então, basicamente o mesmo problema de antes.

Então, como eu poderia chamar uma função de manipulador de componente de formulário C # (por exemplo, clique) de outro manipulador de componente de formulário, aguardar a conclusão e, em seguida, chamar outra função - sem gerar uma exceção?

c#
  • 2 2 respostas
  • 21 Views

2 respostas

  • Voted
  1. Stephen Cleary
    2023-09-04T18:33:03+08:002023-09-04T18:33:03+08:00

    Se você quiser apenas chamar um método de outro, isso funcionaria:

    private void btn_my_Click(object sender, EventArgs e)
    {
      radio_button_special.PerformClick();
      do_rest_of_processing();
    }
    

    Task.Runfilas funcionam no pool de threads, o que está incorreto aqui.

    Se você tiver um trabalho longo a fazer, será melhor para seus usuários se você executar esse trabalho em um thread de pool de threads. A solução adequada nesse caso é refatorar seu código para que haja outro método que possa ser chamado tanto pelo clique do botão de opção quanto pelo clique deste botão.

    • 1
  2. Best Answer
    jtxkopt
    2023-09-04T05:29:41+08:002023-09-04T05:29:41+08:00

    Task.Runenfileira o método fornecido para execução em um thread do pool de threads. Portanto, você ainda está acessando o controle de outro thread, mesmo executando uma invocação. Em vez disso, você deve chamar o Control.Invokeinterior do arquivo Task.Run.

    private async void button1_Click(object sender, EventArgs e)
    {
        await Task.Run(() =>
        {
            radioButton1.Invoke(() => radioButton1.PerformClick());
        });
    }
    

    EDIT: o que funcionou para o pôster do OP foi:

    private async void button1_Click(object sender, EventArgs e)
    {
        await Task.Run(() =>
        {
            radioButton1.Invoke((MethodInvoker) delegate { radioButton1.PerformClick(); });
        });
    }
    
    • 0

relate perguntas

  • Polly DecorrelatedJitterBackoffV2 - como calcular o tempo máximo necessário para concluir todas as novas tentativas?

  • Wpf. Role o DataGrid dentro do ScrollViewer

  • A pontuação que ganhei na página do jogo com .NET MAUI MVVM não é visível em outras páginas. Como posso manter os dados de pontuação no dispositivo local

  • Use a hierarquia TreeView com HierarchicalDataTemplate de dentro de um DataTemplate

  • Como posso melhorar essa interface de validação no .NET?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve