Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Приложение зависает при переключении языка, Многопоточное приложении зависает IME 
:(
    Опции темы
Illusion Dolphin
Дата 23.5.2011, 23:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Delphi 2010, Windows7 (вроде бы и на XP так же).
В настройках языка необходимо иметь более 1 языка (рус, англ к примеру). 
В дополнительныз настройках переключения языка настраиваем:
  - Язык1 переключается через ctrl+shift+1
  - Язык2 переключается через ctrl+shift+2
  ...
В приложении поток TT:

Код

uses
  Classes, ADODB, Windows, ActiveX, SysUtils;
...
procedure TT.Execute;
var
  Conn: TADOConnection;
begin
  CoInitializeEx(nil, 0);
  Conn:= TADOConnection.Create(nil);

  while True do
  begin
    Sleep(100);
    Synchronize(
      procedure
      begin
        Form1.Caption := 'Updated in thread via an anonymous method'
      end
      )
   end;
end;


Само приложение:

Код

procedure TForm1.FormCreate(Sender: TObject);
begin
  CoInitializeEx(nil, 0); // не обязательно
  TT.Create(False);
end;


Запускаем приложение, фокус на единственную Edit на форме и МЕНЯЕМ язык с помошью вышеуказанной комбинацией (IME). Приложение зависает :(

Кто может установить причину и как избавиться?
Если использовать только одну форму без других оконных обработчкиков то это исправляется так:
(AevMainMessage - ApplicationEvents.OnMessage, FSetLanguageMessage - зарегистрированное сообщение)
Код


procedure TXXXX.AevMainMessage(var Msg: tagMSG;
  var Handled: Boolean);
var
  Count: Cardinal;
  LpList: array [0 .. 9] of HKL;
  BFound: Boolean;
  I: Integer;
begin
  if Msg.message = FSetLanguageMessage then
    ActivateKeyboardLayout(HKL(Msg.LParam), KLF_ACTIVATE or KLF_SUBSTITUTE_OK or KLF_REPLACELANG);

  if Msg.message = WM_INPUTLANGCHANGEREQUEST then
  begin
    Handled := True;
    if GetKeyboardLayout(0) = HKL(Msg.LPARAM) then
      Exit;
    Count := GetKeyboardLayoutList(0, LpList);
    if (Count = 0) then
      Exit;

    Count := GetKeyboardLayoutList(SizeOf(LpList), LpList);
    BFound := FALSE;
    for I := 0 to Count - 1 do
    begin
      if (HKL(Msg.LParam) = LpList[I]) then
      begin
        BFound := TRUE;
        Break;
      end
    end;

    if BFound then
      PostThreadMessage(GetCurrentThreadID, FSetLanguageMessage, Msg.LParam, Msg.LParam);
  end;
end;


Решение не подходит из-за того что в таком случае ошибка возникает и диалогах открытия или сохранения файла т.к. у них другая оконная процедура.
Тестовое приложение в аттаче.

Заранее спасибо!


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
CodeMonkey
Дата 24.5.2011, 04:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

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





--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Illusion Dolphin
Дата 24.5.2011, 08:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата

Посмотрите http://www.gunsmoker.ru/2010/06/blog-post_08.html 

Посмотрел. Там ничего касающего вопроса нету. В момент переключения языка (после того как программа не обработала WM_INPUTLANGCHANGEREQUEST) главная нитка потока "Blocked on SendMessage call to a window owned by Thread XXXX", где XXXX поток TT. Для эксперемента я увеличивал Sleep(100000) и пото в момент зависания был в Sleep и даже не нелал никаких синхронизаций (это оказалось избыточной информацией):

Главный поток:

Код

:773f6344 ntdll.KiFastSystemCallRet
:7752732e USER32.DefWindowProcW + 0xe3
:77527308 USER32.DefWindowProcW + 0xbd
:7752729f USER32.DefWindowProcW + 0x54
:74ff7113 ; C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7600.16661_none_420fe3fa2b8113bd\comctl32.dll
:74ff70d1 ; C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7600.16661_none_420fe3fa2b8113bd\comctl32.dll
:775286ef ; C:\Windows\system32\USER32.dll
:77528876 ; C:\Windows\system32\USER32.dll
:775243cf USER32.WindowFromDC + 0xeb
:775243f5 USER32.CallWindowProcW + 0x1b
:0048022d TWinControl.DefaultHandler + $DD
:0048012d TWinControl.WndProc + $56D
:0047f7cb TWinControl.MainWndProc + $2F
:004438c2 StdWndProc + $16
:775286ef ; C:\Windows\system32\USER32.dll
:77528876 ; C:\Windows\system32\USER32.dll
:775289b5 ; C:\Windows\system32\USER32.dll
:77528e9c USER32.DispatchMessageW + 0xf


Поток:
Код

:773f6344 ntdll.KiFastSystemCallRet
:773f4a7c ntdll.ZwDelayExecution + 0xc
:75621818 KERNELBASE.Sleep + 0xf
Unit2.TT.Execute
:004413f1 ThreadProc + $45
:00406322 ThreadWrapper + $2A
:75a31194 kernel32.BaseThreadInitThunk + 0x12
:7740b429 ntdll.RtlInitializeExceptionChain + 0x63
:7740b3fc ntdll.RtlInitializeExceptionChain + 0x36


Ещё идеи будут?


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
CodeMonkey
Дата 24.5.2011, 09:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

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



Цитата
Там ничего касающего вопроса нету.


Лолшто?  smile 

Что и говорить, "Как узнать почему зависла программа" не имеет никакого отношения к вопросу "Почему приложение зависает при переключении языков", ага.

Ладно, посмеялись, ближе к делу smile

Цитата
В момент переключения языка (после того как программа не обработала WM_INPUTLANGCHANGEREQUEST) главная нитка потока "Blocked on SendMessage call to a window owned by Thread XXXX", где XXXX поток TT.


Вот она, ваша причина зависания программы: банальный deadlock. Главный поток ждёт отмашки от TT, а он её не делает, ибо...  вообще никогда не делает. 

Ссылка на поднятие уровня знаний: http://www.transl-gunsmoker.ru/2010/05/blog-post.html  Вот она как раз не совсем по теме, но показывает направление поиска.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Illusion Dolphin
Дата 25.5.2011, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата

Ссылка на поднятие уровня знаний: http://www.transl-gunsmoker.ru/2010/05/blog-post.html  Вот она как раз не совсем по теме, но показывает направление поиска.


Спасибо, теперь причина зависания понятна. И раз мы отдалились от "темы", то тогда совсем не по теме - решение проблемы (а вдруг кому пригодится):

Код

    TpImmDisableIME = function(idThread: DWORD ): BOOL; stdcall;
...
    hModuleImm32 := LoadLibrary('imm32.dll');
...
    pImmDisableIME := GetProcAddress(hModuleImm32, 'ImmDisableIME');
...
    pImmDisableIME(0);


Это применять для каждого треда который надо "разгрузить" от лишних сообщений.

Ещё раз спасибо, было интересно что является первопричиной.


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




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


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

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