Como faço para retornar um valor de um thread?
c#
.net
multithreading
Sam
fonte
fonte
lock(value) { value = "Hello world"; }
seria melhor lidar com a gravação de vários valores de thread?value
está ocorrendo ao mesmo tempo. Mas, sim, sempre esteja atento quando um bloqueio é necessário.Depende de como você deseja criar o thread e a versão .NET disponível:
.NET 2.0+:
A) Você pode criar o
Thread
objeto diretamente. Neste caso, você pode usar "closure" - declarar a variável e capturá-la usando a expressão lambda:B) Você pode usar delegados e
IAsyncResult
valor de retorno doEndInvoke()
método:C) Você pode usar a
BackgroundWorker
classe. Neste caso, você pode usar a variável capturada (como com oThread
objeto) ou manipular oRunWorkerCompleted
evento:.NET 4.0+:
A partir do .NET 4.0, você pode usar a biblioteca paralela de tarefas e a
Task
classe para iniciar seus threads. A classe genéricaTask<TResult>
permite que você obtenha o valor de retorno daResult
propriedade:.NET 4.5+:
A partir do .NET 4.5, você também pode usar
async
/await
keywords para retornar o valor da tarefa diretamente em vez de obter aResult
propriedade:Nota: o método, que contém o código acima, deve ser marcado com a
async
palavra - chave.Por muitas razões, o uso da Biblioteca Paralela de Tarefas é a maneira preferível de trabalhar com threads.
fonte
Eu usaria a abordagem BackgroundWorker e retornaria o resultado em e.Result.
EDITAR:
Isso é comumente associado a WinForms e WPF, mas pode ser usado por qualquer tipo de aplicativo .NET. Este é um exemplo de código para um aplicativo de console que usa BackgroundWorker:
Resultado:
ATUALIZAÇÃO DE 2014
Veja a resposta de @ Roger abaixo.
https://stackoverflow.com/a/24916747/141172
Ele ressalta que você pode usar uma Tarefa que retorna um
Task<T>
e verifiqueTask<T>.Result
.fonte
Um thread não é um método - você normalmente não "retorna" um valor.
No entanto, se estiver tentando recuperar um valor dos resultados de algum processamento, você terá muitas opções, sendo as duas principais:
Realmente depende de como você está criando o thread e como deseja usá-lo, bem como da linguagem / estrutura / ferramentas que está usando.
fonte
Minha classe favorita executa qualquer método em outro thread com apenas 2 linhas de código.
uso
Esteja ciente de que longFunctionComplete NÃO será executado no mesmo encadeamento que starthework.
Para métodos que usam parâmetros, você sempre pode usar fechamentos ou expandir a classe.
fonte
Aqui está um exemplo simples usando um delegado ...
Há uma série fantástica sobre threading em Threading em C # .
fonte
Basta usar a abordagem de delegado.
Agora faça a função Multiply que funcionará em outro thread:
fonte
Eu me deparei com este segmento ao tentar obter o valor de retorno de um método que é executado dentro de um segmento. Pensei em postar minha solução que funcionasse.
Esta solução usa uma classe para armazenar o método a ser executado (indiretamente) e armazena o valor de retorno. A classe pode ser usada para qualquer função e qualquer tipo de retorno. Você apenas instancia o objeto usando o tipo de valor de retorno e, em seguida, passa a função para chamar por meio de um lambda (ou delegado).
Implementação C # 3.0
Para usar este código, você pode usar um Lambda (ou um delegado). Aqui está o exemplo usando lambdas:
Implementação VB.NET 2008
Qualquer pessoa usando o VB.NET 2008 não pode usar lambdas com métodos de retorno sem valor. Isso afeta a
ThreadedMethod
classe, então faremosExecuteMethod
retornar o valor da função. Isso não machuca nada.fonte
Com o .NET Framework mais recente, é possível retornar um valor de um thread separado usando uma Task, onde a propriedade Result bloqueia o thread de chamada até que a tarefa seja concluída:
Para obter detalhes, consulte http://msdn.microsoft.com/en-us/library/dd537613(v=vs.110).aspx
fonte
Delegados ThreadStart em C # usados para iniciar threads têm o tipo de retorno 'void'.
Se você deseja obter um 'valor de retorno' de uma thread, você deve escrever em um local compartilhado (de uma maneira segura para thread) e ler a partir daí quando a thread tiver concluído a execução.
fonte
Se você não quiser usar um BackgroundWorker e apenas usar um Thread normal, pode disparar um evento para retornar dados como este:
fonte
thread1_
parte da fiação do AsyncCompletedEventHandler . Se minha edição estava errada, por favor me ajude a entender o que estava acontecendo lá.thread1_Thread1Completed +=
porquethread1_Thread1Completed
é o nome de uma função, portanto, você não pode colocá-lo no lado esquerdo de um operador de atribuição. O lado esquerdoThread1Completed +=
é usado porque é um evento, portanto, pode aparecer no lado esquerdo do operador de atribuição para adicionar manipuladores de eventos. Verpublic event AsyncCompletedEventHandler Thread1Completed;
#region
seção antes. Eu olhei. Honesto! :)Threads realmente não têm valores de retorno. No entanto, se você criar um delegado, poderá invocá-lo de forma assíncrona por meio do
BeginInvoke
método. Isso executará o método em um thread do pool de threads. Você pode obter qualquer valor de retorno de como chamada viaEndInvoke
.Exemplo:
GetAnswer
será executado em um thread do pool de threads e, quando concluído, você poderá recuperar a respostaEndInvoke
como mostrado.fonte
O BackgroundWorker é bom quando se desenvolve para Windows Forms.
Digamos que você queira passar em uma aula simples de um lado para outro:
Eu escrevi uma curta aula que faz o seguinte:
De dentro da rotina de discussão:
Adicionar um delegado pode ser útil para postar seus dados diretamente de volta ao thread principal, mas você pode precisar usar Invoke se alguns dos itens de dados não forem seguros para thread.
Para testar isso, crie um pequeno aplicativo de console e coloque-o no arquivo Program.cs :
Aqui está uma captura de tela do que obtive com isso:
Espero que outras pessoas possam entender o que tentei explicar.
Gosto de trabalhar em tópicos e usar delegados. Eles tornam o C # muito divertido.
Apêndice: Para codificadores VB
Eu queria ver o que estava envolvido na escrita do código acima como um aplicativo de console VB. A conversão envolveu algumas coisas que eu não esperava, então irei atualizar este tópico aqui para aqueles que desejam saber como encadear em VB.
fonte
fonte
test(){ Thread.Sleep(5000); /*Highly time demanding process*/ return "Returned from test()";}
. Nesse caso, o encadeamento autônomo não teria tempo para atribuir um novo valor àreturnValue
variável. Como último recurso, você pode salvar uma referência de threadvar standaloneThread = new Thread(()=> //...);
e, depois disso, iniciá-la de forma sincronizadastandaloneThread.Start(); standaloneThread.Join();
. Mas essa certamente não é a melhor prática.Uma solução simples é passar um parâmetro por ref para a função que está sendo executada no thread e alterar seu valor no thread.
Se você não pode alterar a função que está sendo executada na banda de rodagem, pode envolvê-la em outra função:
fonte
Pode usar este código:
fonte
Não sou especialista em threading, é por isso que fiz assim:
Eu criei um arquivo de configurações e
Dentro do novo tópico:
Então, pego esse valor sempre que preciso.
fonte