Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.87/54: Рейтинг темы: голосов - 54, средняя оценка - 4.87
215 / 215 / 20
Регистрация: 18.05.2010
Сообщений: 865

Как вызвать функцию по завершении работы потока

29.02.2012, 12:33. Показов 10583. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Допустим мы запускаем какой то поток и нам надо вызвать какую нить функцию после завершение потока, как это сделать, если нам известен только метод вызова потока.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    public interface IStart
    {
        void execute();
    }
    public class ThreadControl
    {
        public ThreadControl()
        {
        }
 
        public void Start(IStart task)
        {
            new Thread(task.execute).Start();
        }
 
        private void OnComplete()
        {
            // здесь выполнить после завершение потока 
            // как попасть сюда после завершееение потока ???
        }
    }
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
29.02.2012, 12:33
Ответы с готовыми решениями:

QThread как очищать память при завершении работы потока?
В моей минипрограммке используется класс наследованный от QThread. Этот объект в качестве полей класса имеет динамически создаваемые...

Как при завершении главного потока прерывать фоновые потоки?
При завершении главного потока фоновые прерываются. Как сделать?

Уведомление о завершении потока
Надоело велосипедить, пора разобраться (хотя с виду вроде все просто должно быть...) Собственно проблема: public class Custom { ...

10
84 / 84 / 10
Регистрация: 20.05.2011
Сообщений: 145
29.02.2012, 13:18
Используйте BackgroundWorker.
0
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
29.02.2012, 18:58
Предположим BackgroundWorker не нужен, а этот вопрос появился при реализации какой-то специфической задачи.

Можно сделать что-то типа этого:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using System;
using System.Threading;
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            ConcreteTask[] tasks =
            {
                new ConcreteTask("Первая задача"),
                new ConcreteTask("Вторая задача"),
                new ConcreteTask("Третья задача"),
                new ConcreteTask()
            };
 
            ThreadControl thrControl = new ThreadControl();
            for (int i = 0; i < tasks.Length; i++)
            {
                thrControl.Start(tasks[i]);
            }
 
            Console.ReadKey();
        }
    }
}
C#
1
2
3
4
5
6
    public interface ITask
    {
        string Name { get; }
        void DoWork();
        event EventHandler Completed;
    }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    public class ThreadControl
    {
        public ThreadControl()
        {
        }
 
        public void Start(ITask task)
        {
            task.Completed += delegate(object sender, EventArgs e)
            {
                OnComplete((ITask)sender);
            };
            Thread thread = new Thread(task.DoWork);
            thread.Start();
        }
 
        private void OnComplete(ITask task)
        {
            //конечно тут не нужно я думаю с интерфейсом взаимодействовать
            //это просто для примера. Тут выполняем нашу специфичискую задачу
            Console.WriteLine("Задача \"{0}\" завершила работу", task.Name);
        }
    }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    public class ConcreteTask : ITask
    {
        string _name;
 
        public ConcreteTask()
            : this(Guid.NewGuid().ToString()) //скорее просто для удобства различия задач :)
        {
        }
 
        public ConcreteTask(string name)
        {
            _name = name;
        }
 
        public void DoWork()
        {
            Console.WriteLine("Выполняется задача");
            Thread.Sleep(Randomizer.Instance().Random.Next(750));
            OnComplete();
        }
 
        public string Name { get { return _name; } }
 
        /// <summary>Происходит после завершения работы задачи текущего экземпляра</summary>
        public event EventHandler Completed;
 
        private void OnComplete()
        {
            if (Completed != null)
                Completed(this, EventArgs.Empty);
        }
    }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    //это вообще к вопросу не относится, просто чтобы рандом давал точно разные значения
    public sealed class Randomizer 
    {
        static Randomizer _randomizer;
        static object _sunc = new object();
        public Random Random { get; private set; }
 
        private Randomizer()
        {
            Random = new Random();
        }
 
        public static Randomizer Instance()
        {
            //чтобы не лочить каждое обращение, так как null будет только 1 раз
            //хотя в данном примере преимуществ от этого нету
            if (_randomizer == null) 
            {
                lock (_sunc)
                {
                    //теперь ещё раз проверяем, чтобы не создать несколько объектов, 
                    //остальные потоки после lock уже не создадут новые объекты
                    if (_randomizer == null) 
                    {
                        _randomizer = new Randomizer();
                    }
                }
            }
 
            return _randomizer;
        }
    }
Добавлено через 35 минут
Только обратил внимание, в классе ThreadControl в методе OnComplete(ITask task) скорее всего нужна будет какая-то синхронизация, ведь в этот метод "полезут" все потоки.
0
215 / 215 / 20
Регистрация: 18.05.2010
Сообщений: 865
29.02.2012, 20:08  [ТС]
Casper-SC, вы удалились от условия задачи .
Цитата Сообщение от Башир Посмотреть сообщение
public interface IStart
{
void execute();
}
есть интерфейс только такого рода и нельзя туда впихивать что то своего, потому что дается только такой интерфейс который запускаеп приложение по вызову execute. Но я в принципе разобрался, а решается она при помощи делегата, ведь делегат это готовы поток в чистом виде.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    public interface IStart
    {
        void execute();
    }
 
    public class ThreadControl
    {
        private delegate void Execute();
        
        public ThreadControl()
        {
        }
 
        public void Start(IStart task)
        {
            Execute start = task.execute;
            start.BeginInvoke(OnComplete, null);
        }
 
        private void OnComplete(IAsyncResult itf)
        {
            lock (this)
            {
                // здесь выполнить после завершение потока 
            }
        }
    }
делегаты сами по себе отличное решение во многих случаях когда нужна многопоточность. и крайне редко приходится воспользоваться случем когда нужен сам класс Thread.
0
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
29.02.2012, 21:49
Цитата Сообщение от Башир Посмотреть сообщение
Casper-SC, вы удалились от условия задачи
И где об этом было сказано? Ну да ладно. А создать новый интерфейс унаследованный от IStart? Хотя кто его знает, что там за задача у вас была (имею ввиду её условия).
0
215 / 215 / 20
Регистрация: 18.05.2010
Сообщений: 865
29.02.2012, 23:01  [ТС]
Дело в том что нам известен только один метод класса который реализует интерфейс ITask в котором только один метод, а других данных у нас нет и мы не можем другой класс подписать на событие заверщение, ведь событие завершение надо ставить в самом классе который реализует этот интерфейс, а вот чтобы сам экземпляр объекта Thread как то сообщал об окончании потока я не нашел.... можно либо по таймеру проверять о том что завершен поток или нет либо не использовать Thread а вместо него делегат, хотя не знаю думаю должен быть у Thread что то подобное но я как то не нашел
0
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
29.02.2012, 23:17
Я не пойму, разве нельзя сделать так?
C#
1
2
3
4
5
6
7
8
9
10
    public interface IStart
    {
        void execute();
    }
 
    public interface ITask : IStart
    {
        string Name { get; }
        event EventHandler Completed;
    }
И использовать код, который я приводил выше? Ведь можно же.

Добавлено через 1 минуту
C#
1
        private delegate void Execute();
Тут и делегат Action подойдёт.

Добавлено через 6 минут
Цитата Сообщение от Башир Посмотреть сообщение
мы не можем другой класс подписать на событие заверщение, ведь событие завершение надо ставить в самом классе который реализует этот интерфейс
Ну дык и надо было сказать сразу, что нельзя самому реализовать класс наследующий от IStart

Добавлено через 1 минуту
Тоесть как я понял нельзя нам писать класс ConcreteTask, эти классы уже есть, а нужно подругому определять, что поток завершил работу? Ладно, если задача решена, то можно не продолжать диалог. Смысла нету.
0
215 / 215 / 20
Регистрация: 18.05.2010
Сообщений: 865
01.03.2012, 10:16  [ТС]
Цитата Сообщение от Casper-SC Посмотреть сообщение
а нужно подругому определять, что поток завершил работу?
в принципе задача решена но было бы интересно узнать как можно грамотно определить завершил ли поток свою работу. Причем от самого Thread. Но я ничего не нашел такого.
0
fazanis31
01.03.2012, 10:29
посмотрите здесьвсе в видео уроках
215 / 215 / 20
Регистрация: 18.05.2010
Сообщений: 865
01.03.2012, 14:10  [ТС]
если не иметь доступ к классу метод которого запускается из потока то никак нельзя в момент завершения потока вызвать какую то функцию, потому что на это нет события.
C#
1
2
3
4
5
6
7
8
9
10
      Thread thread = new Thread(execute);
      thread.Start();
 
      // к сожаление нету ничего такого побобного
      thread.Completed += OnComplete;
 
      // можно только получить его состояние
      if (thread.ThreadState != ThreadState.Running)
      {
      }
0
11 / 11 / 0
Регистрация: 16.09.2013
Сообщений: 75
08.06.2015, 11:59
Я правильно понял, что в основном потоке нет события или возможности отловить событие когда закончит работу рабочий поток?
Результат работы рабочего потока я получил в основном потоке, но мне нужно руками (buttonclick например) проверять и обрабатывать результат.
В голову приходит только сделать таймер который каждую секунду будет спрашивать "а не поменялась ли переменная"...

ЗЫ. Про BackgroundWorker вкурсе (пока учусь через new Thread)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
08.06.2015, 11:59
Помогаю со студенческими работами здесь

Многопоточность: вызвать метод главного потока из второстепенного потока
Здравствуйте. Эта тема всеми избита, знаю. Но у меня очень ограничено время, поэтому рискую и пишу вопрос тут: Пишу приложение...

Ошибка при завершении потока
Есть класс DBmanager, для работы с базой данных. По содержанию примерно такой: class DBmanager :public QThread { Q_OBJECT public: ...

Как вызвать два потока одновременно
После вызова очередного потока появляется ошибка &quot;Нельзя создать более одного экземпляра System.Windows.Application в одном...

При завершении потока программа вылетает
вроде все работает но почему завершается AccesViolation вкурить немогу( unit reg; interface uses Windows, Messages,...

Не очищается память при завершении потока
Добрый день уважаемые форумчане. Из главного потока создаю поток который работает в цикле while not Terminated do. В этом цикле при...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Подключение Box2D v3 к SDL3 для Android: физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru