Модераторы: Partizan, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не убивается процесс, Многопоточность 
:(
    Опции темы
sindi8
  Дата 1.8.2005, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 6.6.2005
Где: Москва

Репутация: нет
Всего: нет



Всем привет.
Никак не могу одолеть грабли - создаю я ассинхронный процесс, процесс запускается и отрабатывает что от него требуется. Но при закрытии формы приложение остается висеть в списке запущенных процессов в task manager-e. Не подскажите как с этим бороться? Делаю следующим образом:

Код

delegate void ScanDriveDelegate(string dir, int i);
...
private void Init()
{
ScanDriveDelegate scanDrive = new ScanDriveDelegate(ScanDrive);
scanDrive.BeginInvoke(comboBox1.Items[comboBox1.SelectedIndex].ToString(), 0, null, null);
}

private void ScanDrive(string dir, int i)
{
...
//Рекурсия
...
}

PM MAIL   Вверх
arilou
Дата 1.8.2005, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Великий МунаБудвин
****


Профиль
Группа: Экс. модератор
Сообщений: 2646
Регистрация: 15.7.2004
Где: город-герой Минск

Репутация: 21
Всего: 61



Ты не мог бы привести полный текст программы?


--------------------
user posted imageuser posted image
PM WWW ICQ   Вверх
sindi8
Дата 1.8.2005, 16:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 6.6.2005
Где: Москва

Репутация: нет
Всего: нет



Выглядит все примерно так (выбросил блок сгенеренный студией и Dispose):
Код

public class Form1 : System.Windows.Forms.Form
{
    private System.Windows.Forms.Button button1;
    private System.Windows.Forms.Label label1;
    private System.Windows.Forms.ListBox listBox1;
    private System.Windows.Forms.Label label2;
    private System.Windows.Forms.ComboBox comboBox1;
    private System.Windows.Forms.ProgressBar progressBar1;
    delegate void ScanDriveDelegate(string dir, int i);
    private System.ComponentModel.Container components = null;

    public Form1()
    {
        InitializeComponent();
        //Список доступных дисков
        string[] drives = Directory.GetLogicalDrives();
        foreach (string s in drives)
            comboBox1.Items.Add(s);
    }

    [STAThread]
    static void Main() 
    {
        Application.Run(new Form1());
    }

    private void button1_Click(object sender, System.EventArgs e)
    {
        progressBar1.Visible = false;
        button1.Enabled = false;
        comboBox1.Enabled = false;
        //Запускаю процесс
        ScanDriveDelegate scanDrive = new ScanDriveDelegate(ScanDrive);
        scanDrive.BeginInvoke(comboBox1.Items[comboBox1.SelectedIndex].ToString(), 0, null, null);
    }

    private void ScanDrive(string dir, int i)
    {
        try
        {
            string[] dirs;
            if (i==0)
            {
                dirs = new string[] {dir};
                Directory.GetDirectories(dir);
            }
            else
                dirs = Directory.GetDirectories(dir);
            foreach (string s in dirs)
            {
                try
                {
                    //Ищу файлы ворда
                    string[] files = Directory.GetFiles(s,"*.doc");
                    foreach (string filepath in files)
                        listBox1.Items.Add(filepath);
                    label1.Text = s;
                    DirectoryInfo di = new DirectoryInfo(s);
                    if ((di.Attributes & FileAttributes.Directory) != 0)
                    {
                        ScanDrive(s, i+1);
                    }
                }
                catch {}
            }
            if (i==0)
            {
                label1.Text = "Поиск файлов завершен. Идет обработка...";
                    progressBar1.Visible = true;
                    progressBar1.Maximum = listBox1.Items.Count;
                    int counter=0; //Указатель текущей позиции прогресбара
                    StreamWriter sw = File.CreateText("tmp.log");
                    foreach (string filepath in listBox1.Items)
                    {
                        counter++;
                        progressBar1.Value = counter;
                        try
                        {
                        //Курочу найденные файлы
                        }
                        catch
                        {
                            //Не удается изменить параметры файла. Записываем в лог-файл
                            sw.WriteLine(filepath);
                        }
                    }
                    sw.Close();
                    label1.Text = "Операция завершена.";
                    progressBar1.Visible = false;
                    button1.Enabled = true;
                    comboBox1.Enabled = true;
                }
            }
            catch (Exception ex)
            {
                //Должно выскакивать когда произошло обращение к несуществующей области
                MessageBox.Show(ex.Message,"Ошибка");
                button1.Enabled = true;
                comboBox1.Enabled = true;
            }
        }
    }

Если нужен полностью рабочий пример - могу скинуть в мыло.
PM MAIL   Вверх
mr.DUDA
Дата 1.8.2005, 17:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Скорее всего, вызываемый асинхронно поток по какой-то причине не завершает работу, а остаётся висеть.
Добавлено @ 18:00
З.Ы, только что увидел:
Цитата
label1.Text = "Поиск файлов завершен. Идет обработка...";
progressBar1.Visible = true;
progressBar1.Maximum = listBox1.Items.Count;

Так делать нельзя. С формой и контролами можно работать только в их "родных" потоках, а из других потоков - только с использованием метода Control.Invoke. Возможно, именно по этой причине глюки.


--------------------
user posted image
PM MAIL WWW   Вверх
sindi8
Дата 1.8.2005, 18:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 6.6.2005
Где: Москва

Репутация: нет
Всего: нет



Спасибо за наводку. Не знал про это. Попробую, может действительно из-за этого.
З.Ы. правда думал что сборщик мусора ВСЕ прибивает при завершении приложения. smile
PM MAIL   Вверх
arilou
Дата 1.8.2005, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Великий МунаБудвин
****


Профиль
Группа: Экс. модератор
Сообщений: 2646
Регистрация: 15.7.2004
Где: город-герой Минск

Репутация: 21
Всего: 61



Цитата(sindi8 @ 1.8.2005, 18:11)
правда думал что сборщик мусора ВСЕ прибивает при завершении приложения

GC тут ни при чем. Может не работать из-за того, что в потоке Exception происходит. Он подвисает, и из-за этого приложение не завершает работу.


--------------------
user posted imageuser posted image
PM WWW ICQ   Вверх
mr.DUDA
Дата 1.8.2005, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



arilou, вполне может висеть потому, что форма вроде как бы уже закрывается (и может даже закрылась), а в это время к ней обращается др. поток с попыткой подвинуть прогрессбар... Или любой другой потенциальный дедлок. Кстати, в .NET 2.0 такие "наезды" на контрол (им. ввиду код, взаимодействующий с контролом или формой из др. потока) приводят к exception -- имхо, здравая идея. Как известно, в .NET все контролы и формы реализованы на "старом добром" WinAPI, а он шуток не любит...


--------------------
user posted image
PM MAIL WWW   Вверх
-ser-
Дата 2.8.2005, 07:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 344
Регистрация: 1.2.2005

Репутация: 5
Всего: 13



Цитата
при закрытии формы приложение остается висеть в списке запущенных процессов в task manager-e

может быть вас смущает в task manager-e в списке запущенных процессов ваш <project_name>.vshost.exe?
так это от самой студии (если вы используете 2005), он всегда там есть, пока проект открыт. я попробовал ваш код у себя, все корректно отрабатывает (разумеется с вызовом Invoke на контролах, о чем упомянул mr.DUDA. ошибка сия непозволительная в .NET 2.0, но как я полагаю, дело не в этом, поскольку форму вы закрыть все же смогли).

и попробовал ваш код как есть без каких-либо изменений вообще в студии 2003. в task manager-e в списке запущенных процессов появляется <project_name>.exe. при закрытии формы он благополучно исчезает.



--------------------
"Тонкая, однако, работа." 
PM MAIL ICQ   Вверх
sindi8
Дата 2.8.2005, 12:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 6.6.2005
Где: Москва

Репутация: нет
Всего: нет



На счет понимания task manager-а проблем не испытываю.
А вот на счет использования Control.Invoke есть вопрос - правильно ли я понял, что мне нужно написать делегат, в котором бы как раз происходило изменение этих самый свойств контролов? и каким образом этот делегат правильно вызывать: грубо говоря так
Код

label1.Invoke(tmpDelegate);

а в tmpDelegate прописать все нужные изменения контролов основного потока?

Цитата
Может не работать из-за того, что в потоке Exception происходит.

Так в том-то и дело, что все отрабатывается, прогрессбар бегает, значения label1 изменяются ну и т.д. Т.е. внешне проложение работает вполне корректно. Дело по всей вероятности видимо именно в этих Invoke, о которых говорил mr.DUDA и другие.

Цитата
и попробовал ваш код как есть без каких-либо изменений вообще в студии 2003. в task manager-e в списке запущенных процессов появляется <project_name>.exe. при закрытии формы он благополучно исчезает.

Ну если бы все было так же гладко - я думаю данная тема бы не появилась.

Это сообщение отредактировал(а) sindi8 - 2.8.2005, 12:25
PM MAIL   Вверх
arilou
Дата 2.8.2005, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Великий МунаБудвин
****


Профиль
Группа: Экс. модератор
Сообщений: 2646
Регистрация: 15.7.2004
Где: город-герой Минск

Репутация: 21
Всего: 61



Да, именно так. Чтобы не создавать лишних делегатов, можно использовать, например, делегат MethodInvoker

Код

MethodInvoker mi = new MethodInvoker(controlFunction);
label1.Invoke(mi);


где controlFunction - та ф-ция, в которой находится код, изменяющий свойства контрола. Кстати, можно не заморачиваться, и вызызывать Form.Invoke, т.к. на форме не может быть контролов, созданных из других потоков. кроме как создавшего форму.
Добавлено @ 12:29
Цитата(sindi8 @ 2.8.2005, 12:18)
Так в том-то и дело, что все отрабатывается

Тут дело хитрое - я заметил, что если ты вызываешь метод асинхронно, и если в нем исключение происходит, то тогда никто тебе о нем не сообщает, по крайней мере, так было в моем сценарии. Потко просто тихо умирал, и программа не стопалась. Наверное, именно по этой причине .NET 2.0 тебе не сообщил, что у тебя InvalidOperationException, когда ты контролы модифицировал из другого потока.

Это сообщение отредактировал(а) arilou - 2.8.2005, 12:34


--------------------
user posted imageuser posted image
PM WWW ICQ   Вверх
sindi8
Дата 2.8.2005, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 6.6.2005
Где: Москва

Репутация: нет
Всего: нет



Спасибо всем. Сейчас буду тестировать.

Да, и у меня кстати .NET 1.1. По непонятным для меня причинам мне на ящик не пришло подтверждение заявки на 2005-ю студию и соответственно студия не пришла.

Это сообщение отредактировал(а) sindi8 - 2.8.2005, 12:35
PM MAIL   Вверх
arilou
Дата 2.8.2005, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Великий МунаБудвин
****


Профиль
Группа: Экс. модератор
Сообщений: 2646
Регистрация: 15.7.2004
Где: город-герой Минск

Репутация: 21
Всего: 61



Да, именно так smile Сча подредактирую
Цитата(sindi8 @ 2.8.2005, 12:31)
но вы случаем не опечатались


Добавлено @ 12:41
Цитата(sindi8 @ 2.8.2005, 12:31)
Да, и у меня кстати .NET 1.1

Тогда все понятно, в 1.1. такой фичи не было (насчет перехвата таких ситуаций).


--------------------
user posted imageuser posted image
PM WWW ICQ   Вверх
sindi8
Дата 2.8.2005, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 6.6.2005
Где: Москва

Репутация: нет
Всего: нет



На счет MethodInvoker - его видимо можно использовать только в том случае, если функция, выполняющая нужные дествия с контролами, без параметров. Если есть параметры - нужно все таки делегаты самому создавать. Или я заблуждаюсь?
PM MAIL   Вверх
arilou
Дата 2.8.2005, 12:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Великий МунаБудвин
****


Профиль
Группа: Экс. модератор
Сообщений: 2646
Регистрация: 15.7.2004
Где: город-герой Минск

Репутация: 21
Всего: 61



Так и есть.


--------------------
user posted imageuser posted image
PM WWW ICQ   Вверх
sindi8
Дата 2.8.2005, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 6.6.2005
Где: Москва

Репутация: нет
Всего: нет



Проблема решена. Всем большое спасибо. Все решилось путем использования Control.Invoke и описанием делегатов, ссылающихся на функции обработки необходимый действий над контролами.

Вопрос на засыпку smile Как отловить завершение ассинхронного потока? Я отлавливал внутри самой функции. Извне как-то можно? EndInvoke имеет к этому отношение?

Это сообщение отредактировал(а) sindi8 - 2.8.2005, 14:22
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0586 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.