В Mono .Net Threads этот поток держится или? - PullRequest
0 голосов
/ 17 января 2019

Это в Unity / Mono, но любой .Net ...

Представьте себе код, подобный этому

using System.Threading;
using System.Runtime.InteropServices;

public class Example: MonoBehaviour {

    [DllImport("__Internal")] private static extern void long_function();
    [DllImport("__Internal")] private static extern void short_function();
    public Thread happyThread;
    public void Test() {

        happyThread = new Thread(LongTest);
        happyThread.Start();
    }
    private void LongTest() { long_function(); }
    private void ShortTest() { short_function(); }
}

Мы запускаем Test и, таким образом, long_function из библиотеки C запускается. Запускается в другом потоке. ("happyThread")

Скажите, что для запуска требуется 60 секунд.

  1. В конце того времени happyThread перестает существовать? Или это все еще там в Примере? Или вы можете сохранить его или что-то ??

  2. Допустим, мы знаем, long_function закончено. Затем я хочу позвонить ShortTest и, следовательно, short_function. Можете ли вы сделать что-то вроде этого ..

Раньше мы это делали

        happyThread = new Thread(LongTest);

Можем ли мы теперь "изменить" содержимое потока на

        happyThread.newStuff( ShortTest());
        happyThread.StartAgain();

или это глупо и бессмысленно?

  1. Могу ли я просто снова запустить ShortTest просто в другой новой теме?

  2. Скажем, в библиотеке есть простая глобальная переменная int k ...

Итак, TBC, файл C, который создается из статической библиотеки, выглядит так:

// file happyLibrary.c Fattie(TM) 2019
#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>
int k = 7; // (NB you almost certainly want volatile here in real apps)
void long_function
{
    ...
  1. ... который long_function устанавливается равным 42. На самом деле .... будет ли short_function позже также иметь доступ к этому значению ?? Или же? Только если я использую ту же тему или что-то? Опять же, k является глобальным глобальным.

  2. если вам нужно запустить миллионы небольших задач, если, возможно, есть преимущество в производительности при повторном использовании happyThread, если вы можете использовать их ??

(Я полностью ценю, что long_function сохранится там и предложит обратные вызовы для основного потока с концепцией short_function; но мне интересно, о чем я спрашиваю выше. Можете ли вы -использовать "ветку"? Можете ли вы снова войти в нее?)

1 Ответ

0 голосов
/ 17 января 2019
  1. В конце того времени, перестает ли существовать happyThread? Или это все еще там в Примере? Или вы можете сохранить его или что-то ??

Когда функция, вызываемая в потоке (в данном случае LongTest), заканчивает, жизненный цикл потока заканчивается. Поток по-прежнему существует до тех пор, пока у вас есть ссылка на него в happyThread (вы можете убедиться сами! happyThread.ManagedThreadId по-прежнему будет возвращать идентификатор потока, даже после его завершения), но его нельзя перезапустить. Вы можете проверить состояние потока, вызвав happyThread.ThreadState (который в этот момент вернет stopped).

Можем ли мы теперь "изменить" содержимое потока на

happyThread.newStuff( ShortTest());
happyThread.StartAgain();

Нет, вы не можете. Вы не можете связать новую функцию с потоком, который уже завершен, и если вы попытаетесь вызвать happyThread.Start() для нее снова, она выдаст ThreadStateException Thread has already been started..

Могу ли я просто снова запустить ShortTest только в другой новой теме?

Да. Вам нужно будет запустить ShortTest для new Thread(ShortTest) (или вы можете просто добавить его в конец метода LongTest(). Любой новый метод, запущенный в потоке, будет выполняться в этом потоке). Однако вы можете вызвать новый поток на старый happyThread. так что happyThread = new Thread(ShortTest()) будет снова счастлив! Вы даже можете начать новый поток в happyThread до того, как закончится первый поток. так

Thread happyThread = new Thread(LongTest());//say this runs for 1 minute
happyThread.Start();
happyThread = new Thread(ShortTest());//this will start without a problem
happyThread.Start();

И с радостью начнется. Обратите внимание, что это не должно быть сделано на самом деле. Это приведет к потере ссылки на поток, выполняющий LongTest. (И несмотря на то, что сначала вызывается LongTest, ShortTest может на самом деле начать работать первым, если этот поток случится первым ... это действительно далеко от идеала, но просто хотел показать, что возможно . )

будет вызывать short_function для последующего доступа к этому значению?

Да, давайте предположим, что int k является общедоступным и глобальным и работает только в основном потоке. Вы можете установить его значение от long_function до 42, а затем прочитать значение int k из short_function в потоке , отличном от , если хотите. Теперь обратите внимание, что вы должны быть осторожны с установкой / получением переменных в нескольких потоках, чтобы предотвратить условия гонки .

Если, однако, вы определите int k внутри метода, работающего в отдельном потоке, он выйдет из области видимости, когда поток умрет, точно так же, как любая переменная, инициализированная внутри функции, когда функция закончится.

Вы можете использовать ключевое слово volatile, чтобы указать, что переменная может быть изменена несколькими потоками. Msdn docs

если вам нужно запустить миллионы маленьких заданий ...

Если вы будете запускать / закрывать большое количество потоков, вы, вероятно, захотите использовать ThreadPools

Можете ли вы как-то "повторно использовать" тему? Можете ли вы снова войти в нее?

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

Однако в качестве альтернативы вы можете поддерживать поток в течение всего времени работы приложения, если вы знаете, что будете вызывать его много или даже постоянно (например, я использую это для поддержания TCP-соединения в фоновом режиме). это должно быть всегда доступно). Это можно сделать так:

Void Start()
{
    Thread happyThread = new thread(() => KeepAlivethread(1000));//short, easy way to create a delegate so you can pass parameters to your thread aswell!
    happyThread.Start();
}

volatile bool keepThreadAlive = true;//volatile because it may be accessed from another thread

private void KeepAliveThread(int timeout)
{
    Debug.Log("Thread started with id: " + Thread.CurrentThread.ManagedThreadId); 
    while (keepThreadAlive)
    {
        //do something, maybe have an event that calls to ShortTest.
        Thread.Sleep(timeout);
    }
    Debug.Log("Thread terminating with id: " + Thread.CurrentThread.ManagedThreadId);
}

Теперь этот поток будет работать в фоновом режиме до тех пор, пока вы не установите keepThreadAlive = false, после чего он корректно завершится. (сделайте так, чтобы вам не нужно было thread.Abort(), что плохо! (подробнее об этом в ответе на предыдущую ссылку в SO)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...