2010-06-11 31 views
13

मैं डेल्फी में एक बहु थ्रेडेड एप्लिकेशन लिख रहा हूं और साझा संसाधनों की सुरक्षा के लिए कुछ उपयोग करने की आवश्यकता है।डेल्फी - क्या सी # लॉक के बराबर है?

सी # में मैं "ताला" कीवर्ड का उपयोग करेंगे:

private someMethod() { 
    lock(mySharedObj) { 
     //...do something with mySharedObj 
    } 
} 

डेल्फी में मैं इसी तरह कुछ भी नहीं मिला, मैंने पाया बस TThread.Synchronize (someMethod) विधि है, जो फोन करके संभावित टकराव से बचाता है मुख्य VCL सूत्र में someMethod है, लेकिन यह वास्तव में नहीं है कि मैं क्या करना चाहते हैं ....

संपादित करें: मैं डेल्फी 6 का उपयोग कर रहा

+1

कम से कम आप कॉल कर सकते हैं खिड़कियों एपीआई महत्वपूर्ण वर्गों – Arseny

उत्तर

17

(अन) सौभाग्य से आप मनमाने ढंग से वस्तुओं पर डेल्फी 6 में बंद नहीं कर सकते (हालांकि आप 200 9 और बाद के संस्करणों में हाल के संस्करणों में) कर सकते हैं, इसलिए आपको इसकी आवश्यकता है एक अलग ताला वस्तु, आमतौर पर एक महत्वपूर्ण खंड।

TCriticalSection (ध्यान दें: प्रलेखन FreePascal से है, लेकिन यह रूप में अच्छी तरह डेल्फी में मौजूद है):

उदाहरण कोड:

type 
    TSomeClass = class 
    private 
    FLock : TCriticalSection; 
    public 
    constructor Create(); 
    destructor Destroy; override; 

    procedure SomeMethod; 
    end; 

constructor TSomeClass.Create; 
begin 
    FLock := TCriticalSection.Create; 
end; 

destructor TSomeClass.Destroy; 
begin 
    FreeAndNil(FLock); 
end; 

procedure TSomeClass.SomeMethod; 
begin 
    FLock.Acquire; 
    try 
    //...do something with mySharedObj 
    finally 
    FLock.Release; 
    end; 
end; 
+1

डेल्फी 2009 किसी भी वस्तु पर एक ताला पाने की क्षमता शुरू की - "क्यों TObject का आकार डेल्फी 2009 में दोगुनी हो गई है" देख http://blogs.teamb.com/craigstuntz/2009/03/25/38138/ – mjn

+2

हाँ, मैंने कुछ समय बाद इसके बारे में सीखा लेकिन सवाल पहले ही डेल्फी 6 का उल्लेख करने के लिए संपादित किया गया था इसलिए मैंने अपना जवाब अपडेट करने से परेशान नहीं किया बस इसे सामने वाले पृष्ठ पर टक्कर मारने के लिए। हालांकि मुझे एक टिप्पणी छोड़नी चाहिए थी। लेकिन, मैं यह कहने के लिए एक नोट दूंगा कि मैं उस लेख में विचार का विरोध करता हूं। किसी ऑब्जेक्ट को लॉक करने की क्षमता * अच्छी * चीज नहीं है, और यदि आप नहीं जानते कि आप क्या कर रहे हैं तो आसानी से डेडलॉक्स का कारण बन सकते हैं। चूंकि कोई भी किसी ऑब्जेक्ट को लॉक कर सकता है, कभी-कभी वे करते हैं। विशेष रूप से लॉकिंग ऑब्जेक्ट आवंटित करना और उनको उपयोग करना बेहतर है। कोई आश्चर्य नहीं (उस संबंध में।) –

0

के रूप में कहा, लघु कोड के लिए है, जो बाहर फोन नहीं करता है स्थानीय दायरा और कोई अन्य ताले हासिल नहीं करता है, आप SyncObjs.TCriticalSection,
के माध्यम से SyncObjs.TMutex का उपयोग कर सकते हैं, जो प्रतीक्षा योग्य (टाइमआउट के साथ) का उपयोग कर सकते हैं, तो स्वामित्व वाले धागे मरने पर रोक नहीं सकते हैं और किसी अन्य प्रक्रियाओं के साथ नाम से साझा किया जा सकता है।
इन रैपर का उपयोग सिंक्रनाइज़ेशन परत में परिवर्तन को आसान बनाता है। , my answer to Difference between the WaitFor function for TMutex delphi and the equivalent in win32 API

3

हालांकि सी # के रूप में पूरी तरह से के रूप में आसान नहीं निम्नलिखित आप के लिए काम कर सकते हैं:

सभी मामलों में, यहाँ ड्रेगन के सावधान रहना।

with Lock(mySharedObj) do 
    begin 
    //...do something with mySharedObj 
    UnLock; 
    end; 

संक्षेप

  • एक सूची में हर उदाहरण आप की रक्षा करना चाहते हैं के लिए रखा जाता है।
  • जब दूसरा थ्रेड Lock(mySharedObj) को कैल्स करता है, तो आंतरिक सूची को मौजूदा लॉक के लिए खोजा जाएगा। यदि कोई मौजूदा लॉक नहीं मिला तो एक नया लॉक बनाया जाएगा। यदि नया धागा अभी भी लॉक है तो नया धागा अवरुद्ध हो जाएगा।
  • Unlock आवश्यक है क्योंकि हम यह सुनिश्चित नहीं कर सकते कि आईएलॉक इंस्टेंस का संदर्भ केवल से पर कॉल करने वाले विधि के से बाहर हो जाएगा। (यदि हम कर सकते हैं, Unlock हटाया जा सकता है)।

ध्यान दें कि यह डिजाइन में, एक TLock हर वस्तु उदाहरण तुम्हारे बिना यह मुक्त किया जा रहा है जब तक आवेदन समाप्त हो जाता है की रक्षा करना चाहते हैं के लिए बनाया जाता है।
इसमें फैक्टर किया जा सकता है लेकिन इसमें _AddRef & _Release के साथ गड़बड़ करना शामिल होगा।


unit uLock; 

interface 

type 
    ILock = interface 
    ['{55C05EA7-D22E-49CF-A337-9F989006D630}'] 
    procedure UnLock; 
    end; 

function Lock(const ASharedObj: TObject): ILock; 

implementation 

uses 
    syncobjs, classes; 

type 
    _ILock = interface 
    ['{BAC7CDD2-0660-4375-B673-ECFA2BA0B888}'] 
    function SharedObj: TObject; 
    procedure Lock; 
    end; 

    TLock = class(TInterfacedObject, ILock, _ILock) 
    private 
    FCriticalSection: TCriticalSection; 
    FSharedObj: TObject; 
    function SharedObj: TObject; 
    public 
    constructor Create(const ASharedObj: TObject); 
    destructor Destroy; override; 
    procedure Lock; 
    procedure UnLock; 
    end; 

var 
    Locks: IInterfaceList; 
    InternalLock: TCriticalSection; 

function Lock(const ASharedObj: TObject): ILock; 
var 
    I: Integer; 
begin 
    InternalLock.Acquire; 
    try 
    //***** Does a lock exists for given Shared object 
    for I := 0 to Pred(Locks.Count) do 
     if (Locks[I] as _ILock).SharedObj = ASharedObj then 
     begin 
     Result := ILock(Locks[I]); 
     Break; 
     end; 

    //***** Create and add a new lock for the shared object 
    if not Assigned(Result) then 
    begin 
     Result := TLock.Create(ASharedObj); 
     Locks.Add(Result); 
    end; 
    finally 
    InternalLock.Release; 
    end; 
    (Result as _ILock).Lock; 
end; 

{ TLock } 

constructor TLock.Create(const ASharedObj: TObject); 
begin 
    inherited Create; 
    FSharedObj := ASharedObj; 
    FCriticalSection := TCriticalSection.Create; 
end; 

destructor TLock.Destroy; 
begin 
    FCriticalSection.Free; 
    inherited Destroy; 
end; 

procedure TLock.Lock; 
begin 
    FCriticalSection.Acquire; 
end; 

function TLock.SharedObj: TObject; 
begin 
    Result := FSharedObj; 
end; 

procedure TLock.UnLock; 
begin 
    FCriticalSection.Release; 
end; 

initialization 
    Locks := TInterfaceList.Create; 
    InternalLock := TCriticalSection.Create; 

finalization 
    InternalLock.Free; 
    Locks := nil 

end. 
+0

लॉक्स सूची को किसी भी तरह से सॉर्ट करने और प्रदर्शन सुधार के लिए बाइनरी खोज के माध्यम से "पता लगाने" की आवश्यकता होगी। –

+0

@ केन बोरासा: सच है, सुधार के लिए बहुत सी जगह बाकी है। हालांकि उद्देश्य यह दिखाने के लिए था कि सी # में उपयोग किए जाने वाले समान निर्माण को डेल्फी 6 के साथ कैसे किया जा सकता है। –

11

डेल्फी 6. में कोई समकक्ष नहीं है डेल्फी 2009 के रूप में, आप मनमाने ढंग से वस्तुओं पर ताले हड़पने के लिए System.TMonitor तरीकों का उपयोग कर सकते हैं।

System.TMonitor.Enter(obj); 
try 
    // ... 
finally 
    System.TMonitor.Exit(obj); 
end; 

(आप "सिस्टम" उपसर्ग जरूरत है क्योंकि प्रपत्र इकाई में प्रकार के साथ TMonitor नाम विरोध करता है। वैकल्पिक वैश्विक MonitorEnter और MonitorExit कार्यों का उपयोग करने के लिए है।)

0

का उपयोग वर्ग सहायकों आप कर सकते हैं इसे इस्तेमाल करो। हालांकि पुराने संस्करणों के साथ काम नहीं करेंगे। लेकिन मैं केवल XE5 में टीएमओनिटर का उपयोग करने की सलाह दूंगा। चूंकि टीआरटीएलक्रिटिकलसेक्शन की तुलना में काफी धीमी है।

http://www.delphitools.info/2013/06/06/tmonitor-vs-trtlcriticalsection/

THelper = class helper for TObject 
    procedure Lock; 
    procedure Unlock; 
end; 

procedure THelper.Lock; 
begin 
    System.TMonitor.Enter(TObject(Self)); 
end; 

procedure THelper.Unlock; 
begin 
    System.TMonitor.Exit(TObject(Self)); 
end;