"Not Responding" वास्तव में क्या है — Windows ऐप के hang का फैसला कैसे करता है, और hang न करने वाले ऐप कैसे design करें
· अद्यतन तिथि: · Go Komura · Windows, Windows development, troubleshooting, multithreading, WinForms, WPF, Win32 API, UI design
संशोधन इतिहास (पहला संस्करण, 22 Aug 2026 को प्रकाशित)
- पहला प्रकाशन
इस लेख का हवाला दें(DOI: 10.5281/zenodo.22176669)
यह लेख Zenodo पर संग्रहीत है। नीचे वह DOI है जो हमेशा नवीनतम संस्करण की ओर ले जाता है, और वह DOI भी जो आपके पढ़े जा रहे संस्करण से बँधा है।
Go Komura (2026). "Not Responding" वास्तव में क्या है — Windows ऐप के hang का फैसला कैसे करता है, और hang न करने वाले ऐप कैसे design करें. KomuraSoft LLC. https://doi.org/10.5281/zenodo.22176669 https://comcomponent.com/hi/blog/windows-app-not-responding-hang-mechanism/
- DOI (नवीनतम संस्करण)
- 10.5281/zenodo.22176669
- DOI (यह संस्करण)
- 10.5281/zenodo.22176670
“Operation के बीच ऐप सफेद हो जाता है और (Not Responding) दिखाता है।” “हमें ticket मिलते हैं कि कभी-कभी hang होता है, पर development machine पर कभी reproduce नहीं होता।” — Windows business ऐप के लिए यह “Not Responding” सबसे आम शिकायतों में से एक है। और हैरानी की बात यह है कि बहुत कम लोग जानते हैं कि “Not Responding” display लगाने वाली चीज़ hang ऐप स्वयं नहीं — वह OS है।
Windows कैसे जानता है कि ऐप “hang” हो गया? वह पाले जैसी सफेद window क्या है? Windows पर business ऐप लिखने वाले developers और hang ऐप के ticket लेने वाले IT staff के लिए, यह लेख message loop की बुनियाद से “Not Responding” decision चलाता है, और hang के classic कारण, hang न करने वाले design, तथा hang के क्षण investigate करने की प्रक्रिया — सब primary sources पर आधारित — व्यवस्थित करता है।
1. निष्कर्ष पहले
- “Not Responding” OS का decision है। जब window (और उसका owner UI thread) input की wait न कर रही हो, startup sequence में न हो, और 5 सेकंड से message (
PeekMessage) न लिया हो, तो OS उसे not responding मानता है। Decision per-process नहीं।1 - सफेदी वाली window “ghost window” है। OS ने original window छिपाई और उसी position, size, और appearance की नकली लगा दी। केवल move, minimize, या close कर सकते हैं; content नहीं चल रही। Debugger जुड़े रहते ghost window नहीं बनती।2
- Hang का कारण लगभग हमेशा एक बात पर आता है। जो UI thread message loop pump कर रहा होना चाहिए वह भारी काम या wait पर block है। Synchronous I/O, network call, lock wait, और thread-across
SendMessageclassic हैं।3 - Design सिद्धांत है “UI thread पर wait या computation न करें”। भारी काम worker thread पर ले जाएँ (C# में
async/await+Task.Run) और UI thread को painting, progress, और cancellation accept के लिए dedicated रखें।4 DoEventsऔर manual message loop pump reentrancy bug का प्रजनन स्थल हैं। “Not Responding” display चला जाता है, पर structure अब मनमाने event को काम के बीच interrupt देने देती है। टालना नहीं, offload सही तरीका है।- Investigation hang क्षण की state पकड़ने से शुरू होती है। Dump लें और UI thread का stack देखें, तो लगभग हमेशा पहचान सकते हैं कि वह किसकी wait कर रहा है।
2. पूर्वापेक्षा: Windows ऐप messages से चलते हैं
“Not Responding” समझने के लिए, पहले यह समझना चाहिए कि Windows GUI ऐप event-driven है। GUI ऐप input स्वयं जाकर नहीं लाता; वह OS द्वारा दिए messages (mouse, keyboard, repaint request, timer, आदि) पाता है और उन पर काम करता है।3
हर thread जो window बनाता है उसके पास message queue होती है और वह ऐसा message loop चलाता है।
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg); // the window procedure is called
}
GetMessage queue से message लेता है, और DispatchMessage उस window की window procedure (message-handle function) बुलाता है। Button-click handle, repaint, और WinForms या WPF event handler सब, उबालने पर, इस loop के एक cycle के भीतर चलते हैं।5
flowchart TB
accTitle: Message loop की बुनियादी structure
accDescr: OS mouse, keyboard, और अन्य input thread की message queue में रखता है; UI thread का loop उसे GetMessage से लेता है, DispatchMessage से window procedure बुलाता है, और processing खत्म होने पर loop के top पर लौटता है
os["OS(input, repaint request, timer)"] --> q["Thread message queue"]
q --> gm["GetMessage से लें"]
gm --> dm["DispatchMessage"]
dm --> wp["Window procedure में handle करें"]
wp --> gm
चित्र 1: GUI ऐप का दिल message loop है; हर event handler इस loop के एक cycle के रूप में चलता है।
इस structure का एक महत्वपूर्ण नतीजा है। यदि window procedure (event handler) के भीतर समय लेने वाला काम करें, तो loop उस बीच अगला message नहीं ले सकता। न click पर respond कर सकता है न repaint request पर — यही “hang” वास्तव में है।
यह भी समझना चाहिए कि message दो paths से दिए जाते हैं। PostMessage message queue पर रखता और तुरंत लौटता है, और loop messages क्रम से लेता और process करता है। SendMessage, दूसरी ओर, window procedure सीधे बुलाता है और processing पूरी होने तक caller पर नहीं लौटता।36 वह अंतर chapter 4 की deadlock चर्चा में सीधा जाता है।
flowchart TB
accTitle: Message पहुँचाने के दो paths
accDescr: PostMessage message queue पर रखता और तुरंत लौटता है; message loop messages क्रम से लेता और process करता है। SendMessage window procedure सीधे बुलाता है और processing पूरी होने तक caller पर नहीं लौटता
pm["PostMessage"] --> q2["Queue पर रखें(तुरंत लौटता है)"]
q2 --> loop["Loop क्रम से लेता और process करता है"]
sm["SendMessage"] --> direct["Procedure सीधे बुलाएँ"]
direct --> w2["Processing पूरी होने तक नहीं लौटता"]
चित्र 2: दोनों “message भेजते” हैं, पर queue वाला Post और completion की wait करने वाला Send पूरी तरह अलग स्वभाव रखते हैं।
3. “Not Responding” का decision कैसे होता है — 5-सेकंड नियम और ghost window
तो OS कैसे जानता है कि “यह ऐप hang हो गया”? कसौटी official रूप से documented है। OS window को not responding तब मानता है जब वह input की wait न कर रही हो, startup sequence में न हो, और 5 सेकंड से PeekMessage (message लेना) न बुलाया हो।1 यानी, OS देखता है कि “message loop वास्तव में घूम रहा है” जैसे नाड़ी लें, और यदि 5 सेकंड नाड़ी न हो तो window को not responding मानता है (document कहता है कि यह 5-सेकंड मान भविष्य में बदल सकता है)। Decision की इकाई window और उसका owner UI thread है; कई UI threads वाले ऐप में एक thread hang होने का अर्थ दूसरे thread की window मरी नहीं। Dump में देखने वाला thread hang window का owner है।
जिस top-level window का decision हो चुका उसके साथ क्या होता है यह भी documented है। OS original window छिपाता है और उसी Z-order, position, size, और appearance की “ghost window” से बदल देता है। User केवल move, resize, या (जबरन) close कर सकता है। भीतर का ऐप वास्तव में respond नहीं दे रहा, इसलिए अन्य operations काम नहीं करते।2
flowchart TB
accTitle: Hang-window decision और ghost-window swap
accDescr: जब UI thread भारी काम पर block हो और message लेना 5 सेकंड रुक जाए, OS window को not responding मानता है, original छिपाता है, उसी appearance की ghost window लगाता है, और user को केवल move, minimize, और close देना है
busy["UI thread भारी काम पर block"] --> stop["Message लेना रुकता है"]
stop --> judge{"5 सेकंड बीते?"}
judge -->|"नहीं"| stop
judge -->|"हाँ"| ghost["Ghost window लगाएँ"]
ghost --> u1["Title दिखाता है(Not Responding)"]
ghost --> u2["पाले जैसी सफेदी; केवल move और close"]
चित्र 3: “Not Responding” text और सफेद screen दोनों OS द्वारा लगाई ghost window की हैं, hang ऐप की नहीं।
Title bar पर दिखने वाला “(Not Responding)” string, और Aero theme के अधीन पाले जैसी सफेदी, दोनों इसी ghost window की हैं। दो practical नतीजे निकलते हैं।
- “Not Responding” दिखने तक, उस window का owner thread कम से कम 5 सेकंड message process नहीं कर रहा। यह नहीं कि “display जल्दी आ गया” — UI thread निश्चित रूप से block है।
- Debugger जुड़े रहते ghost window नहीं बनती।2 जब ऐसा लगे कि “debugger के अधीन कभी Not Responding नहीं जाता, पर release में जाता है”, hang स्वयं वही हो सकता है और केवल display अलग।
एक API भी है, DisableProcessWindowsGhosting, जो इस swap को पूरे process के लिए disable करती है।7 यह kiosk terminal जैसे special cases के लिए है जहाँ आप नहीं चाहते कि OS स्वयं window को operate होते दिखाने लगे। इसे call करने से “Not Responding” display आना रुकता है, पर ऐप hang है यह तथ्य नहीं बदलता। समझें कि सामान्य ऐप इसे “Not Responding” उपाय के रूप में इस्तेमाल नहीं करता।
4. ऐप क्यों hang होते हैं — UI thread block करने वाले classic patterns
कारण, उबालने पर, एक बिंदु है — “UI thread message loop पर नहीं लौटता” — पर व्यवहार में जो रूप मिलते हैं वे कुछ classic में पड़ते हैं।
flowchart TB
accTitle: UI thread block करने वाले classic कारणों का वर्गीकरण
accDescr: चार classic परिवार — synchronous I/O और network call, lock wait, thread-across SendMessage, और COM STA marshaling — सभी उसी एक बिंदु पर आते हैं कि UI thread message loop पर नहीं लौट सकता
kind{"कौन सा classic कारण?"}
kind --> io{"I/O या lock?"}
kind --> other{"SendMessage या COM?"}
io --> c1["Sync I/O और network"]
io --> c2["Lock wait"]
other --> c3["SendMessage"]
c3 -.-> c3n["Thread-across"]
other --> c4["COM STA marshaling"]
c1 --> core["UI लौट नहीं सकता"]
c2 --> core
c3 --> core
c4 --> core
core --> ar["Not Responding जाँच"]
चित्र 4: दिखने वाला symptom एक है, पर thread block करने वाला अपराधी चार परिवारों में पड़ता है, और उपाय प्रत्येक के लिए अलग है।
Synchronous I/O और network call। यह सबसे आम है। Button-click handler के भीतर बड़ी फ़ाइल पढ़ना या लिखना, database query, Web API call, या network drive पर फ़ाइल पहुँच synchronous करने का pattern। Development machine पर यह सेकंड के अंश में खत्म होता है, इसलिए पता नहीं चलता; production network latency या file-server हिचक दसियों सेकंड की wait बना देता है, और ticket आते हैं कि “कभी-कभी hang होता है”। Network drive connection गिरने पर लंबे timeout रखते हैं, और symptom नाटकीय रूप से बदतर करते हैं।
Lock wait। वह pattern जिसमें UI thread worker thread से shared data पर lock लेने की कोशिश करता है, और उस lock को लंबे समय पकड़े worker की wait में फँस जाता है। Lock discipline practical multithreading series में विस्तार से है।
Thread-across SendMessage। SendMessage destination window की procedure processing पूरी करने तक नहीं लौटता।6 जब दूसरे thread की window पर भेजें, भेजने वाले को तब तक wait करवाई जाती है जब तक वह thread message process कर सकने वाली state में हो। यदि destination thread स्वयं किसी चीज़ की wait कर रहा हो, तो message deadlock होता है जिसमें हर पक्ष दूसरे की wait करता है।3 खासकर HWND_BROADCAST पर भेजना आपको खींच लेगा जैसे ही एक window respond न दे। जब wait नहीं कर सकते, SendMessageTimeout या उत्तर की wait न करने वाला PostMessage सोचें।8
sequenceDiagram
accTitle: Thread-across SendMessage से deadlock
accDescr: यदि worker thread UI-thread window पर SendMessage भेजे जबकि UI thread worker के result की wait में block हो, हर पक्ष दूसरे के खत्म होने की wait करता है और deadlock होता है
participant U as UI thread
participant W as Worker thread
U->>U: Worker के खत्म होने की wait(block)
W->>U: SendMessage(process होने तक नहीं लौटता)
Note over U: Message process नहीं कर सकता(block)
Note over W: SendMessage से नहीं लौट सकता
Note over U,W: एक-दूसरे की wait — deadlock
चित्र 5: “UI thread worker की wait करे, और worker SendMessage से UI thread की wait करे” classic deadlock है।
COM apartment marshaling। STA object की call window message के रूप में दी जाती है, इसलिए जब UI thread (STA) block हो, अन्य threads से COM call भी collateral रूप से block हो जाती हैं। वह structure COM STA/MTA लेख में समझाई गई है।
“यह तो क्षण भर है” का ढेर। 50 ms की synchronous call भी, loop में 100 बार बुलाई, 5 सेकंड है। Not Responding सीमा 5 सेकंड है, पर महसूस होने वाली “सुस्ती” लगभग 100 ms से शुरू होती है। Design का अंगूठा नियम है “UI thread केवल milliseconds के लिए block हो सकता है”।
5. Hang न करने वाले design — भारी काम को UI thread से हटाना
Design सिद्धांत एक बात है: समय लेने वाला काम UI thread से हटाएँ। C# (WinForms/WPF) में, async/await सबसे छोटा सही तरीका है।
private async void RunButton_Click(object sender, EventArgs e)
{
runButton.Enabled = false;
try
{
// CPU-heavy work, or APIs that are only synchronous, go to a worker via Task.Run
var result = await Task.Run(() => HeavyCalculation(input));
// For I/O, use APIs that are natively async (they do not consume a thread either)
var data = await httpClient.GetStringAsync(url);
// After await you are back on the UI thread, so you can touch controls directly
resultLabel.Text = result + data.Length.ToString();
}
catch (Exception ex)
{
// An exception leaking from an async void handler will take the app down. Catch it here
MessageBox.Show($"The operation failed: {ex.Message}");
}
finally
{
runButton.Enabled = true;
}
}
तीन बिंदु हैं। पहला, await wait करते UI thread message loop में वापस होता है, इसलिए Not Responding नहीं जाते। दूसरा, await के बाद continuation UI thread पर लौटती है, इसलिए बाद में control सामान्य छू सकते हैं (worker thread से control सीधे छूना वर्जित है; यदि चाहिए तो Control.Invoke / Dispatcher.InvokeAsync इस्तेमाल करें)।4 तीसरा, काम चलते बटन disable करें, और अन्यथा design से reentrancy मारें।
रूप native Win32 में वही है: काम worker thread को सौंपें, completion UI thread को PostMessage से custom message के रूप में सूचित करें, और window procedure में UI update करें। PostMessage केवल message queue पर रखता और तुरंत लौटता है, इसलिए worker पक्ष भी block नहीं होता।6 Worker thread की wait स्वयं condition-variable लेख में वर्णित discipline से लिखें।
flowchart TB
accTitle: Hang न करने वाले ऐप में भूमिकाओं का विभाजन
accDescr: UI thread केवल input accept, progress दिखाना, और cancellation accept के लिए जिम्मेदार है; worker thread भारी काम चलाता है और completion UI thread को PostMessage या await continuation से लौटाता है
ui["UI thread: input, progress, cancel"] -->|"काम सौंपें"| w["Worker thread: भारी काम"]
w -->|"PostMessage / await continuation"| ui
ui -.-> ng["UI thread पर synchronous I/O या लंबी computation नहीं"]
चित्र 6: UI thread को “reception desk” रखें, भारी काम हमेशा worker को सौंपें, और केवल completion notification लें।
जो बचाना चाहिए वह तकनीक है भारी काम के टुकड़ों के बीच केवल display जीवित रखने के लिए Application.DoEvents() या PeekMessage loop घुसाना। Not Responding टलता है, पर मनमाने event handlers काम के बीच re-enter करते हैं। बटन का दूसरा click, processing के दौरान form close, timer fire — कोई भी अभी process हो रहे data को corrupt कर सकता है, और bug timing-dependent तथा मुश्किल-से-reproduce होते हैं। Manual message loop pump को modal progress dialog जैसी सीमित structure के भीतर रखें, और नियमतः offload से हल करें।
sequenceDiagram
accTitle: DoEvents से reentrancy bug की timeline
accDescr: भारी काम के बीच DoEvents call करने से queue में click का event handler interrupt कर चल सकता है, अभी process हो रहे data को लिख सकता है, और फिर original काम फिर शुरू होता है, जिससे timing-dependent data corruption होता है
participant U as UI thread
U->>U: भारी काम शुरू(data process हो रहा)
U->>U: DoEvents(queue messages process करें)
Note over U: बटन-reclick handler interrupt करता है
U->>U: Interrupt काम data लिखता है
U->>U: Original काम फिर शुरू(data पहले से inconsistent)
चित्र 7: DoEvents “Not Responding” मिटाता है, बदले में मनमाने events को काम के बीच आमंत्रित कर।
लंबे चलने वाले काम के लिए, design में progress display और cancellation भी शामिल करें। Progress IProgress<T> से UI को भेजें और interrupt CancellationToken से बताएँ, तो user देख सकता है कि “काम हो रहा है” और जबरन termination की ओर नहीं जाएगा (जो अक्सर data corruption का कारण होती है)।
flowchart TB
accTitle: लंबे काम के लिए progress और cancellation flow
accDescr: Worker thread progress IProgress से UI thread को भेजता है; UI पर cancel action CancellationToken से worker तक पहुँचती है; worker सुविधाजनक सीमा पर रुकता और साफ़ करता है
w3["Worker: लंबा काम"] -->|"IProgress से progress"| ui2["UI: progress और stop बटन"]
ui2 -->|"CancellationToken"| w3
w3 --> stop2["सीमा पर रुकें और साफ़ करें"]
चित्र 8: Progress है “worker → UI”; cancellation है “UI → worker”। यह पतला bidirectional channel design में शुरू से शामिल करें।
6. Hang क्षण की investigation
“कभी-कभी hang होता है” की investigation में सबसे मूल्यवान चीज़ है ठीक hang क्षण की thread state। Reboot करें, और सबूत चला जाता है।
Dump लें। Task Manager के Details tab पर target process पर right-click → “Create dump file”। इतना ही हर thread के stack वाला full dump देता है। Ticket लेने वाले IT staff से केवल यह कहना कि “जब hang हो, बंद करने से पहले यह लें” investigation की सफलता दर बहुत बदलता है। Collection mechanism बनाने के लिए crash-dump collection लेख देखें।
UI thread का stack देखें। Dump WinDbg में खोलें और message loop pump करने वाले thread (आमतौर पर thread 0) का stack देखें। Synchronous I/O ReadFile या network API के रूप में, lock wait WaitFor… परिवार call के रूप में, और thread-across SendMessage SendMessage के भीतर wait के रूप में — ज्यों का त्यों दिखता है। पढ़ने का तरीका introductory WinDbg लेख में है।
Live देखें। Process Explorer से thread list और stack मौके पर जाँच सकते हैं। जब लगातार सुस्त हो, WPR trace लें और UI thread की waits का समय के साथ analysis करें (practically WPR/WPA)।
flowchart TB
accTitle: Not Responding investigation की बुनियादी प्रक्रिया
accDescr: Hang क्षण पर dump लें, UI thread का stack देखें, पहचानें कि synchronous I/O, lock wait, या thread-across SendMessage पर रुका है, और उसे मेल खाते design सुधार से जोड़ें
hang["Hang क्षण"] --> dump["Dump लें(बंद करने से पहले)"]
dump --> stack["UI thread का stack देखें"]
stack --> io["Synchronous I/O या network wait"]
stack --> lock["Lock wait"]
stack --> sm["Thread-across SendMessage"]
io -.-> fix["साइट को worker पर अलग करें"]
lock -.-> fix
sm -.-> fix
चित्र 9: Investigation का नायक “hang क्षण का dump” है; UI thread का stack स्वयं कारण का वर्गीकरण है।
Symptom से पहली कट कैसे लें यह भी standardize कर सकते हैं। यदि हमेशा special operation पर hang हो, पहले उस handler के भीतर synchronous I/O संदेह करें। यदि दुर्लभ hang हो और operation से कोई संबंध न हो, lock order या thread-across SendMessage deadlock संदेह करें, और dump में दोनों threads के wait target मिलाएँ। यदि केवल special environment में hang हो, network drive, proxy, या antivirus जैसे environment factors से timeout संदेह करें।
7. सारांश
- “Not Responding” वह mechanism है जिसमें OS तय करता है कि ऐप ने 5 सेकंड message नहीं लिया और ghost window लगा देता है। Display लगाने वाली चीज़ OS है, ऐप नहीं।
- Hang का कारण एक बिंदु है: “UI thread message loop पर नहीं लौट सकता”। Synchronous I/O, network, lock wait, और thread-across SendMessage classic हैं।
- उपाय है भारी काम को UI thread से हटाना। C# में
async/await+Task.Run; Win32 में worker thread +PostMessage। Execution के दौरान reentrancy बटन disable करने जैसे design से रोकें। DoEventsसे टालना reentrancy bug के बदले है।DisableProcessWindowsGhostingकेवल display हटाता है। कोई भी root-cause fix नहीं।- Investigation के लिए “hang क्षण” का dump सबसे महत्वपूर्ण है। कारण लगभग हमेशा UI thread के stack पर ज्यों का त्यों लिखा होता है।
User की नज़र से “Not Responding” है “टूट गया”, पर mechanism जानने पर उसे सटीक वाक्य में translate कर सकते हैं “UI thread 5 सेकंड वापस नहीं आया”। उस एक वाक्य से पीछे चलें, तो candidate कारण, fix, और investigation प्रक्रिया सब स्वाभाविक निकलते हैं।
संबंधित लेख
- Spurious wakeup — condition variable “बिना notification के” क्यों जागती है और Windows पर सही wait
- Practical multithreading best practices: .NET संस्करण — और thread जोड़ने से पहले क्या तय करें
- COM STA/MTA की बुनियाद — threading model और hang से बचना
- WinDbg + SOS से crash dump पढ़ना — collection के बाद analysis की practical guide
- Process Explorer / Handle / VMMap practically — hang, leak, और “file in use” को अभी की state से पकड़ना
- आपके ऐप की नज़र से Windows shutdown — exit notifications, restart, और power loss सही संभालना
संबंधित consulting क्षेत्र
KomuraSoft LLC उन business ऐप की root-cause investigation संभालता है जो “कभी-कभी hang” होते हैं या “Not Responding” जाते हैं (dump analysis और trace analysis), synchronous काम से भरे legacy UI code को async/await और worker-thread isolation में refactor करना, तथा न जमने वाले UI design की review। जब reproduce करने की प्रक्रिया अभी न हो, सबूत कैसे इकट्ठा करें उसके design से मदद शुरू कर सकते हैं।
संदर्भ लिंक
-
Microsoft Learn, IsHungAppWindow function (winuser.h). ऐप को not responding मानने की कसौटी पर कि वह “input की wait न कर रहा हो, startup sequence में न हो, और 5 सेकंड के internal timeout से PeekMessage न बुलाया हो”; इस 5-सेकंड कसौटी के बदल सकने पर; और ghost window के लिए function के हमेशा TRUE लौटाने पर। ↩ ↩2
-
Microsoft Learn, GetMessage function (winuser.h). सिस्टम के top-level window को कुछ सेकंड messages पर respond न देने पर not responding मानकर उसी Z-order, position, size, और appearance की ghost window से बदलने पर; user के केवल move, resize, या close करने पर; और debugger जुड़े रहते ghost window न बनने पर। ↩ ↩2 ↩3
-
Microsoft Learn, About Messages and Message Queues. Windows ऐप के event-driven होने और window procedure के messages process करने पर; queued messages और सीधे भेजे messages के भेद पर; not responding window की ghost window से swap पर; और threads के एक-दूसरे को messages भेजने से deadlock cover करने वाले खंड पर। ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, How to make thread-safe calls to controls (Windows Forms). WinForms control के बनाने वाले के अलावा किसी thread से छूने के लिए safe न होने पर; दूसरे thread से update के लिए Invoke/BeginInvoke इस्तेमाल करने पर; और async/await या BackgroundWorker इस्तेमाल करने वाले safe async patterns पर। ↩ ↩2
-
Microsoft Learn, Using Messages and Message Queues. GetMessage, TranslateMessage, और DispatchMessage वाली typical message-loop implementation पर, और message queue जाँचने के तरीके पर। ↩
-
Microsoft Learn, SendMessage function (winuser.h). SendMessage के specified window की window procedure बुलाने और processing पूरी होने तक न लौटने पर; दूसरे thread की window पर भेजने के भेजने वाले को उस thread के message process करने तक wait करवाने पर; और उत्तर की wait न कर message queue पर रखने वाले PostMessage से अंतर पर। ↩ ↩2 ↩3
-
Microsoft Learn, DisableProcessWindowsGhosting function (winuser.h). Calling GUI process के लिए ghost-window सुविधा disable कर सकने पर जो not responding window को minimize, move, और close योग्य बनाती है; और disablement के process के जीवन तक रहने पर। ↩
-
Microsoft Learn, SendMessageTimeout function (winuser.h). Timeout के साथ message भेज सकने पर; और flag (SMTO_ABORTIFHUNG) पर जो window respond न दे (hang मानी गई हो) तो wait किए बिना लौटता है। ↩
संबंधित लेख
निकटवर्ती विषयों में गहराई से जाने के लिए समान टैग वाले नवीनतम लेख।
DllMain और Loader Lock — DLL initialization में "कुछ मत करो" कहा जाने का असली कारण
DllMain से LoadLibrary क्यों न call करें और दूसरे thread से synchronize न करें। Primary sources से यह लेख बताता है कि loader lock हर DLL ...
Win32 Thread Pool API — CreateThreadpoolWork से thread बनाए बिना concurrency
क्या आपके native code में CreateThread calls बिखरी पड़ी हैं? यह लेख Vista में redesign की गई Win32 thread pool API — work, timer, wait और...
Sleep से resume पर टूटने वाले apps — Windows power events कैसे काम करते हैं और उनसे बचने वाले business apps कैसे बनाएँ
Laptop खोला और business app के connections मर चुके थे — कारण वह design है जिसने sleep का हिसाब ही नहीं रखा। यह लेख WM_POWERBROADCAST noti...
Spurious wakeup — condition variable "बिना notification के" क्यों जागती है और Windows पर सही wait कैसे करें
Condition variable की wait notification आए बिना भी लौट सकती है (spurious wakeup)। यह लेख Windows implementation से समझाता है कि spec इसे ...
Clipboard और drag-and-drop कैसे काम करते हैं — business ऐप में OLE data transfer सही संभालना
Excel table paste करें और formatting बिखर जाए; source ऐप बंद करें और paste बंद हो जाए — दोनों इसलिए कि clipboard एक ही content कई formats...
संबंधित विषय
ये पृष्ठ विषय को सेवाओं और निर्णयों के व्यापक संदर्भ में रखते हैं।
Windows के तकनीकी विषय
Windows विकास, बग जाँच और मौजूदा संपत्तियों के उपयोग का प्रवेश-द्वार।
UI थ्रेड और टाइमर
WPF / WinForms का UI थ्रेड, असिंक्रोनस प्रवाह, Dispatcher और टाइमर डिज़ाइन।
इस विषय से जुड़ी सेवाएँ
यह लेख निम्नलिखित सेवाओं से सीधे जुड़ा है।
Windows ऐप विकास
व्यावसायिक ऐप, डिवाइस एकीकरण और संचार उपकरण, आवश्यकताओं से विकास तक।
अक्सर पूछे जाने वाले प्रश्न
इस लेख के विषय पर परामर्श में अक्सर पूछे जाने वाले प्रश्न।
- "Not Responding" किन शर्तों पर दिखता है?
- OS window को hang तब मानता है जब window वाला ऐप input की wait न कर रहा हो, startup sequence में न हो, और 5 सेकंड से message (PeekMessage) न लिया हो। Hang top-level window छिपाई जाती है और उसी position, size, और appearance की "ghost window" से बदली जाती है। "(Not Responding)" title-bar text और पाले जैसी सफेदी इसी ghost window की हैं, जो केवल move, minimize, या close करने देती है। यानी "Not Responding" ऐप स्वयं नहीं दिखाता — यह वह screen है जो OS ऐप की ओर से लगाता है।
- क्या काम चलते "Not Responding" न दिखाने की setting है?
- DisableProcessWindowsGhosting call करने से उस process के लिए ghost window की swap disable हो जाती है। वह केवल hang को user से कम visible बनाता है — window फिर भी input पर respond नहीं करती, और user की नज़र से यह पूरा freeze है जिसमें move या close का रास्ता नहीं। असली fix display दबाना नहीं, भारी काम को worker thread पर ले जाना है ताकि UI thread पाँच सेकंड तो क्या, दसवें सेकंड भी block न हो। ध्यान दें कि debugger जुड़े रहते OS ghost window नहीं बनाता, इसलिए debugging के दौरान ऐसा लग सकता है मानो "Not Responding" कभी होता ही नहीं।
- क्या DoEvents (manual message loop pump) से "Not Responding" बचाना स्वीकार्य है?
- Recommended नहीं। भारी काम के बीच DoEvents या PeekMessage loop घुमाने से hang-window decision टलता है, पर कोई भी event handler फिर re-enter कर सकता है — बटन का दूसरा click, window close, timer, आदि। दूसरा handler अभी process हो रहे data को लिख दे, या बंद मानी गई form छूकर exception फेंके — timing-dependent, मुश्किल-से-reproduce होने वाले reentrancy bug पैदा होते हैं, जो "Not Responding" से भी बदतर हैं। सही तरीका है काम स्वयं Task.Run आदि से worker thread पर ले जाना, और UI thread को केवल progress display और cancellation accept के लिए छोड़ना।
- Worker thread से UI (control) कैसे update करूँ?
- WinForms control और WPF element केवल उसी thread से छूए जा सकते हैं जिसने उन्हें बनाया (आमतौर पर UI thread)। Worker thread से सीधे छूने से exception या undefined behavior होता है। C# में async/await सबसे आसान path है: await के बाद continuation calling UI thread पर लौटती है, इसलिए await के बाद control सामान्य update कर सकते हैं। साफ़-साफ़ marshal करने के लिए, WinForms में Control.Invoke/BeginInvoke और WPF में Dispatcher.InvokeAsync इस्तेमाल करें। Native Win32 में established pattern है worker thread UI thread को custom completion message PostMessage करे, और window procedure UI update करे।
- ऐप के "Not Responding" दिखाने का कारण कैसे investigate करूँ?
- महत्वपूर्ण है hang के "क्षण स्वयं" की state पकड़ना। पहले Task Manager के Details tab से "Create dump file" से full dump लें, फिर WinDbg में UI thread (message loop चलाने वाला thread) का stack देखें। क्या वह synchronous I/O, network wait, lock wait, या SendMessage से दूसरे thread की wait में अटका है — stack पर ज्यों का त्यों दिखता है। Live process देखने के लिए Process Explorer की thread list और stack view useful हैं; समय के साथ देखने के लिए WPR trace पकड़ना प्रभावी है। इस साइट का introductory WinDbg लेख, practically Process Explorer, और practically WPR/WPA भी देखें।