में एफ # इवेंट का उपयोग करना मैं एफ # में एसिंक वर्कफ़्लोज़ और एजेंटों के साथ बहुत कुछ कर रहा हूं, जबकि मैं घटनाओं में थोड़ा गहराई से जा रहा था, मैंने देखा कि इवेंट < _>() प्रकार थ्रेड- सुरक्षित। यहां मैं एक घटना को बढ़ाने की आम समस्या के बारे में बात नहीं कर रहा हूं। मैं वास्तव में एक घटना से सदस्यता लेने और निकालने/निपटाने के बारे में बात कर रहा हूं। परीक्षण के लिए मैं इस छोटे से कार्यक्रमबहु-थ्रेडेड कोड
let event = Event<int>()
let sub = event.Publish
[<EntryPoint>]
let main argv =
let subscribe sub x = async {
let mutable disposables = []
for i=0 to x do
let dis = Observable.subscribe (fun x -> printf "%d" x) sub
disposables <- dis :: disposables
for dis in disposables do
dis.Dispose()
}
Async.RunSynchronously(async{
let! x = Async.StartChild (subscribe sub 1000)
let! y = Async.StartChild (subscribe sub 1000)
do! x
do! y
event.Trigger 1
do! Async.Sleep 2000
})
0
प्रोग्राम सरल है लिखा है, मैं एक घटना और एक समारोह है कि यह करने के लिए घटनाओं की एक विशेष राशि सदस्यता लेता है, और उसके बाद हर हैंडलर निपटाने पैदा करते हैं। मैं Async.StartChild के साथ उन फ़ंक्शन के दो उदाहरणों को उत्पन्न करने के लिए एक और async गणना का उपयोग करता हूं। दोनों कार्यों के समाप्त होने के बाद मैं यह देखने के लिए ट्रिगर करता हूं कि कुछ हैंडलर अभी भी बाकी हैं या नहीं।
लेकिन जब event.Trigger(1)
परिणाम कहा जाता है अभी भी कुछ संचालकों घटना के लिए reigstered हैं कि है। चूंकि कुछ "1" कंसोल पर मुद्रित किए जाएंगे। इसका सामान्य अर्थ यह है कि सब्सक्राइब करना और/या निपटान थ्रेड-सुरक्षित नहीं है।
और है कि मैं उम्मीद नहीं की थी क्या है। यदि सब्सक्राइबिंग और डिस्पोजिंग थ्रेड-सुरक्षित नहीं है तो सामान्य रूप से ईवेंट कैसे सुरक्षित रूप से उपयोग किए जा सकते हैं? निश्चित घटनाओं को थ्रेड के बाहर भी इस्तेमाल किया जा सकता है, और एक ट्रिगर समानांतर या विभिन्न धागे में किसी भी फ़ंक्शन को नहीं बढ़ाता है। लेकिन यह मेरे लिए सामान्य है कि घटनाओं का उपयोग Async, एजेंट आधारित कोड या सामान्य रूप से थ्रेड के साथ किया जाता है। बैकराउंडवर्कर थ्रेड की जानकारी इकट्ठा करने के लिए उन्हें अक्सर संचार के रूप में उपयोग किया जाता है। Async.AwaitEvent के साथ किसी ईवेंट की सदस्यता लेना संभव है। यदि सब्सक्राइबिंग और डिस्पोजिंग थ्रेड-सुरक्षित नहीं है, तो ऐसे माहौल में ईवेंट का उपयोग करना कैसे संभव है? और किस उद्देश्य में Async.AwaitEvent है? यह मानते हुए कि एक Async वर्कफ़्लो थ्रेड को बस Async.AwaitEvent का उपयोग करने की उम्मीद करता है मूल रूप से "डिज़ाइन द्वारा टूटा हुआ" है यदि किसी ईवेंट को सब्सक्राइब करना/डिस्पोजे करना डिफ़ॉल्ट रूप से थ्रेड-सुरक्षित नहीं है।
सामान्य प्रश्न मैं का सामना करना पड़ रहा हूँ है। क्या यह सही है कि सदस्यता और निपटान थ्रेड-सुरक्षित नहीं है? मेरे उदाहरण से ऐसा लगता है, लेकिन शायद मुझे कुछ महत्वपूर्ण जानकारी याद आई। मैं वर्तमान में अपने डिजाइन में इवेंट का बहुत उपयोग करता हूं, मेरे पास आमतौर पर मेलबॉक्स प्रोसेसर होते हैं और अधिसूचना के लिए ईवेंट का उपयोग करते हैं। तो सवाल यह है। यदि घटनाएं थ्रेड-सुरक्षित नहीं हैं, तो वर्तमान में मैं जिस डिज़ाइन का उपयोग कर रहा हूं वह थ्रेड-सुरक्षित नहीं है। तो इस स्थिति के लिए एक फिक्स क्या है? एक नया नया धागा-सुरक्षित घटना कार्यान्वयन बनाना? क्या वे पहले से ही कुछ कार्यान्वयन मौजूद हैं जो इस समस्या का सामना करते हैं? या अत्यधिक थ्रेडेड वातावरण में सुरक्षित रूप से ईवेंट का उपयोग करने के लिए अन्य विकल्प हैं?
आपकी अंतिम वाक्य के लिए। Async.Start के साथ शुरू किया गया प्रत्येक async थ्रेड-पूल पर चलता है, लेकिन यह भी प्रयोग करते हैं! या करो! एसिंक को अन्य थ्रेड पर स्विच कर सकते हैं, उदाहरण के लिए बस "Async.Sleep" का उपयोग थ्रेड-पूल पर स्विच या Async.StartChild का उपयोग कर करता है। शीर्ष पर मैं मेलबॉक्स प्रोसेसर से ईवेंट ट्रिगर कर रहा हूं और वे थ्रेड-पूल पर हमेशा कुछ थ्रेड चलाते हैं। तो मैं नहीं देखता कि सबकुछ एक धागे पर कैसे चलाना है। लेकिन मैं यह व्यवहार भी नहीं चाहूंगा। मैं इस तरह के व्यवहार की उम्मीद कर रहा हूं क्योंकि मैं सब कुछ एक ही धागे पर चलाने के लिए नहीं चाहता हूं। –
ऐसा लगता है कि घटनाओं पर थ्रेड सुरक्षा की कमी F # कोर लाइब्रेरी के साथ एक महत्वपूर्ण समस्या है। क्या आप इसके लिए कोई मुद्दा खोलने पर विचार करेंगे? –
आप अपनी खुद की कोरआउटिन रोल कर सकते हैं या सुनिश्चित कर सकते हैं कि प्रत्येक 'चलो!' 'करो!' "मुख्य-थ्रेड" पर वापस पोस्ट करें। लेकिन जैसा कि आपने कहा था कि आप उस व्यवहार को वैसे भी नहीं चाहते हैं, इससे कोई फर्क नहीं पड़ता। – FuleSnabel