Como você inicia um thread com parâmetros em c #?
c#
multithreading
JL.
fonte
fonte
Respostas:
Sim :
fonte
void MyParamObject(object myUrl){ //do stuff }
deve ter o tipo de parâmetroobject
ParameterizedThreadStart
e claramente do texto da pergunta, provavelmente não é esse o caso.Uma das 2 sobrecargas do construtor Thread leva um delegado ParameterizedThreadStart, que permite passar um único parâmetro ao método start. Infelizmente, embora ele permita apenas um único parâmetro e o faça de maneira insegura, porque passa como objeto. Acho muito mais fácil usar uma expressão lambda para capturar os parâmetros relevantes e transmiti-los de maneira fortemente tipada.
Tente o seguinte
fonte
Dim thr As New Thread(Sub() DoStuff(settings))
Você pode usar expressões lambda
Até agora, essa é a melhor resposta que pude encontrar, é rápida e fácil.
fonte
O tipo de parâmetro deve ser um objeto.
EDITAR:
Embora essa resposta não esteja incorreta, recomendo essa abordagem. Usar uma expressão lambda é muito mais fácil de ler e não requer conversão de tipo. Veja aqui: https://stackoverflow.com/a/1195915/52551
fonte
Parameter
?fonte
Maneira simples usando lambda assim ..
Ou você pode até
delegate
usarThreadStart
assim ...OU usando o VS 2019 .NET 4.5+ ainda mais limpo assim ..
fonte
Use
ParametrizedThreadStart
.fonte
Use ParameterizedThreadStart .
fonte
Como já foi mencionado em várias respostas aqui, a
Thread
classe atualmente (4.7.2) fornece vários construtores e umStart
método com sobrecargas.Esses construtores relevantes para esta pergunta são:
e
que leva um
ThreadStart
delegado ou umParameterizedThreadStart
delegado.Os delegados correspondentes ficam assim:
Portanto, como pode ser visto, o construtor correto a ser usado parece ser aquele que recebe um
ParameterizedThreadStart
delegado, para que algum método em conformidade com a assinatura especificada do delegado possa ser iniciado pelo encadeamento.Um exemplo simples para instanciar a
Thread
classe seriaou apenas
A assinatura do método correspondente (chamada
Work
neste exemplo) se parece com isso:O que resta é iniciar o thread. Isso é feito usando qualquer um
ou
Enquanto
Start()
iniciaria o encadeamento e passarianull
como dados para o método,Start(...)
pode ser usado para passar qualquer coisa para oWork
método do encadeamento.No entanto, há um grande problema com essa abordagem: tudo o
Work
que é passado no método é convertido em um objeto. Isso significa que, dentro doWork
método, ele deve ser convertido para o tipo original novamente, como no exemplo a seguir:A transmissão é algo que você normalmente não deseja fazer.
E se alguém passa outra coisa que não é uma string? Como isso parece impossível no início (porque é o meu método, eu sei o que faço ou O método é privado, como alguém deve ser capaz de transmitir alguma coisa a ele? ), Você pode acabar exatamente com esse caso por vários motivos . Como alguns casos podem não ser um problema, outros são. Nesses casos, você provavelmente terminará com um
InvalidCastException
que provavelmente não notará porque simplesmente encerra o encadeamento.Como solução, você esperaria obter um
ParameterizedThreadStart
representante genérico comoParameterizedThreadStart<T>
ondeT
seria o tipo de dados que você deseja passar para oWork
método. Infelizmente, algo assim não existe (ainda?).Existe, no entanto, uma solução sugerida para esse problema. Envolve a criação de uma classe que contém os dados a serem passados para o encadeamento, bem como o método que representa o método worker como este:
Com essa abordagem, você iniciaria o thread assim:
Portanto, dessa maneira, você simplesmente evita transmitir e tem uma maneira segura de fornecer dados a um thread ;-)
fonte
private static void MyMethod<T>(T myData) { T message = myData; Console.WriteLine($"the thread wrote: {message}"); }
message.Length
não é possível e assim por diante)if(myData.GetType() == typeof(string)) { var str = ((string)(object)myData).Length; }
. Enfim, em vez de usar seu método de encadeamento, achei um pouco mais confortável de usarTasks<T>
, como por exemplotasks.Add(Task.Run(() => Calculate(par1, par2, par3)))
, veja minha resposta abaixo ( stackoverflow.com/a/59777250/7586301 )Eu estava tendo problema no parâmetro passado. Passei o número inteiro de um loop for para a função e a exibi, mas ela sempre dava resultados diferentes. like (1,2,2,3) (1,2,3,3) (1,1,2,3) etc com o delegado ParametrizedThreadStart .
esse código simples funcionou como um encanto
fonte
O
ParameterizedThreadStart
leva um parâmetro. Você pode usar isso para enviar um parâmetro ou uma classe personalizada contendo várias propriedades.Outro método é colocar o método que você deseja iniciar como membro da instância em uma classe, juntamente com as propriedades dos parâmetros que você deseja definir. Crie uma instância da classe, defina as propriedades e inicie o thread especificando a instância e o método, e o método poderá acessar as propriedades.
fonte
Você pode usar um delegado ParametrizedThreadStart :
fonte
Você pode usar o método BackgroundWorker RunWorkerAsync e transmitir seu valor.
fonte
fonte
Eu proponho usar em
Task<T>
vez deThread
; permite vários parâmetros e executa muito bem.Aqui está um exemplo de trabalho:
fonte
fonte