বন্ধ এবং নিষ্পত্তি - কোন কল?


161

থ্রেডগুলি পড়ে স্কেলকম্যান্ডে কি যথেষ্ট? আলোচনা যথেষ্ট? এবং একটি ডাব্লুসিএফ পরিষেবা বন্ধ এবং নিষ্পত্তি আমি SQLConnication বা স্ট্রিম বর্গ থেকে উত্তরাধিকারসূত্রে প্রাপ্ত বেশ কয়েকটি শ্রেণীর মধ্যে একটির জন্য ক্লাসের জন্য কি ভাবছি যে আমি ক্লোজরের পরিবর্তে ডিসপোজ বন্ধ করে দিলে কি আসে যায়?

উত্তর:


191

আমি এই পরিস্থিতিটি পরিষ্কার করতে চাই।

মাইক্রোসফ্টের নির্দেশিকা অনুসারে, Closeউপযুক্ত যেখানে পদ্ধতি প্রদান করা এটি একটি ভাল অনুশীলন । ফ্রেমওয়ার্ক ডিজাইন নির্দেশিকাগুলি থেকে এখানে উদ্ধৃতি দেওয়া আছে

ক্ষেত্রের Close()মধ্যে Dispose()যদি স্ট্যান্ডার্ড পরিভাষাটি কাছাকাছি থাকে তবে এছাড়াও, পদ্ধতি সরবরাহের বিষয়টি বিবেচনা করুন । এটি করার সময়, আপনি Closeবাস্তবায়নটিকে অভিন্ন করার জন্য গুরুত্বপূর্ণ Dispose...

বেশিরভাগ ক্ষেত্রে Closeএবং Disposeপদ্ধতি সমান। মূল পার্থক্য মধ্যে Closeএবং Disposeক্ষেত্রে SqlConnectionObjectহয়:

একটি অ্যাপ্লিকেশন Closeএকাধিকবার কল করতে পারে। কোনও ব্যতিক্রম উত্পন্ন হয় না।

আপনি যদি Disposeপদ্ধতিটি SqlConnectionঅবজেক্টের অবস্থা বলে থাকেন তবে তা পুনরায় সেট করা হবে। যদি আপনি নিষ্পত্তিযোগ্য SqlConnection অবজেক্টে কোনও পদ্ধতিতে কল করার চেষ্টা করেন তবে আপনি ব্যতিক্রম পাবেন।

বলেছিল:

  • আপনি যদি একবার সংযোগ অবজেক্ট ব্যবহার করেন তবে ব্যবহার করুন Dispose।
  • যদি সংযোগ অবজেক্টটি অবশ্যই পুনরায় ব্যবহার করা উচিত, তবে Closeপদ্ধতিটি ব্যবহার করুন ।

5
@ ক্রিস, ক্লোজ () এর ডকুমেন্টেশন বলছে "এটি এর পরে সংযোগ পুলের সাথে সংযোগ ছেড়ে দেয় বা সংযোগ পুলিং অক্ষম থাকলে সংযোগটি বন্ধ করে দেয়" " সুতরাং সংযোগ পুলটি উপচে পড়া থেকে দূরে রাখতে ক্লোজ () যথেষ্ট হওয়া উচিত।
— ডেভিড হ্যামন্ড

@ ডেভিড হ্যামন্ড: আপনি ঠিক বলেছেন। আমি আমার আগের মন্তব্য মুছে ফেলছি।
— নোটমে

3
ডি .পোস ()) সংযোগটিও পুলটিতে ছেড়ে দেয়?
— oscilatingcretin

এক দশকে এই বিষয়টিতে আমি একভাবে বা অন্যভাবে পড়েছি এটি সেরা যুক্তি। দুর্দান্ত পয়েন্ট।
— মাইকেল এরিকসন

1
সুতরাং এটি এইভাবে কাজ করে 1. con.Open() con.Close(); 2 con.Open(); // reuse 3. con.Dispose(); // use one time con.Open(); // error
— শাইজুট

24

যথারীতি উত্তরটি: এটি নির্ভর করে। বিভিন্ন শ্রেণি IDisposableবিভিন্ন উপায়ে প্রয়োগ করে এবং প্রয়োজনীয় গবেষণা করা আপনার উপর নির্ভর করে।

যতদূর SqlClientযায়, প্রস্তাবিত অনুশীলনটি নিম্নলিখিতগুলি করা হয়:

using (SqlConnection conn = /* Create new instance using your favorite method */)
{
    conn.Open();
    using (SqlCommand command = /* Create new instance using your favorite method */)
    {
        // Do work
    }
    conn.Close(); // Optional
}

আপনি সংযোগে কল করা উচিতDispose (বা Close*)! আবর্জনা সংগ্রহকারী আপনার সংযোগ পরিষ্কার করার জন্য অপেক্ষা করবেন না , এটি পরবর্তী জিসি চক্র (কমপক্ষে) পর্যন্ত পুলটিতে সংযোগগুলি আবদ্ধ করবে। যদি আপনি কল করেন Dispose, কল করার দরকার নেই Closeএবং যেহেতু usingকনস্ট্রাক্ট এটি Disposeসঠিকভাবে পরিচালনা করতে এত সহজ করে তোলে তাই কল করার কোনও কারণ নেই Close।

সংযোগগুলি স্বয়ংক্রিয়ভাবে পুল হয় এবং সংযোগে কল করা Dispose/ Closeশারীরিকভাবে সংযোগটি বন্ধ করে না (সাধারণ পরিস্থিতিতে)। নিজের পুলিং বাস্তবায়নের চেষ্টা করবেন না। SqlClientসংযোগটি পুল থেকে পুনরুদ্ধার করা হলে ক্লিনআপ সম্পাদন করে (যেমন ডাটাবেস প্রসঙ্গে এবং সংযোগের বিকল্পগুলি পুনরুদ্ধার করা)।

* যদি আপনি কল করছেন Close, এটি একটি ব্যতিক্রম-নিরাপদ উপায়ে (অর্থাত্ একটি ক্যাচ বা অবশেষে অবরুদ্ধে) করতে ভুলবেন না।


আপনি যখন বলেন, "প্রয়োজনীয় গবেষণাটি করা আপনার উপর নির্ভর করে", তখন এই গবেষণাটি কী? আমি কীভাবে নিশ্চিতভাবে বলতে পারি তার একমাত্র উপায় হ'ল প্রতিবিম্বের মাধ্যমে তবে এটি বেশিরভাগ পরিস্থিতিতে "অবৈধ" হওয়ার খারাপ দিক রয়েছে।
— ঝড়

7
আমি বলব না: conn.Close(); // Optionalএটি alচ্ছিক নয়। এটি অপ্রয়োজনীয় এবং অপ্রয়োজনীয়। আপনি দুটি বার অবজেক্টটি নিষ্পত্তি করছেন এবং এটি কিছু কোড বিশ্লেষণ সরঞ্জাম দ্বারা একটি সতর্কতা হিসাবে চিহ্নিত করা হবে।
— মেটালজিক

@ মেটালজিক আমি সম্মত হ'ল যথাযথ ব্যবহারের সাথে ক্লোজকে কল করা অপ্রয়োজনীয় (এবং কুশ্রী)। যাইহোক, nitpicking: বন্ধ কল করছে না "ত্যাগী" (সৎকার একটি SqlConnection জন্য বন্ধ বোঝা যখন)। এর সাথে তুলনা করুন using (var x = ..) { x.Dispose(); }, xসেক্ষেত্রে সত্যিই "দু'বার নিষ্পত্তি" করা হয়েছে।
— ব্যবহারকারী 2864740

11

আপনাকে ডিসপোজ () কল করতে হবে!

নিষ্পত্তি () বিকাশকারীকে কল করার জন্য, আবর্জনা সংগ্রাহক ফিনালাইজ () কল করে। যদি আপনি আপনার বস্তুগুলিতে ডিসপোজ () কল না করেন তবে যে সমস্ত অপ্রয়োজনীয় সংস্থান তারা ব্যবহার করেছেন তা নিষ্পত্তি করা হবে না যতক্ষণ না আবর্জনা সংগ্রহকারী কাছাকাছি না আসে এবং তাদের উপর চূড়ান্ত কল না করে (এবং কখন ঘটে তা কে জানে)।

এই দৃশ্যের নাম নন ডিস্ট্রিমেন্টিক চূড়ান্তকরণ এবং। নেট বিকাশকারীদের জন্য একটি সাধারণ ফাঁদ। আপনি যদি এমন অবজেক্টগুলির সাথে কাজ করছেন যা আইডিজিপোজযোগ্য প্রয়োগ করে তবে তাদের উপর ডিসপোজ () কল করুন!

http://www.ondotnet.com/pub/a/oreilly/dotnet/news/programmingCsharp_0801.html?page=last

যদিও এমন অনেকগুলি উদাহরণ থাকতে পারে (যেমন এসকিএল সংযোগে) যেখানে আপনি কোনও বস্তুতে ডিস্পোনস () কল করেন এবং এটি কেবল তার সংযোগে ক্লোজ () কল করে বা একটি ফাইল হ্যান্ডেল বন্ধ করে দেয়, প্রায়শই এটি ডিসপোজ () কল করতে আপনার সেরা বেট! যদি না আপনি খুব অদূর ভবিষ্যতে অবজেক্টটিকে পুনরায় ব্যবহার করার পরিকল্পনা করেন।


26
এই মন্তব্য সম্পূর্ণ মিথ্যা। আবর্জনা সংগ্রহকারী কখনই ডাকে না Dispose।
— স্টিফেন ক্লিয়ারি

3
পরিণতি: আপনি যদি প্রয়োগ করা ক্লাসের সাথে না ব্যবহার করেন তবে আপনাকে কল করা উচিত । যদি শ্রেণি বলা হচ্ছে প্রয়োগগুলি আইডিজিপোজযোগ্য এবং আপনি তার পৃষ্ঠায় এর ব্যবহারটি গুটিয়ে রেখেছেন , তবে আপনি (পাং ইচ্ছাকৃত, তাই আমাকে গুলি করুন) দিয়ে নিষ্পত্তি করতে পারেন । ব্যবহার অবশ্য কিছু স্পষ্টভাবে সদ্ব্যবহার সঙ্গে বাঞ্ছনীয় , আমি যতদূর জানি। Dispose() using()IDisposableusing()Dispose()Close()Open()
— রেনি কেবিস

আমি অন্যান্য ডিবিএমএস সম্পর্কে নিশ্চিত নই, তবে আপনি পোস্টগ্রেএসএকএল এ দুটোই করতে পারবেন না । আপনি একবার Closeসংযোগ স্থাপন করার পরে, পোস্টগ্রিস স্বয়ংক্রিয়ভাবে সংযোগ শনাক্তকারীকে সেট করে null। সেখান থেকে, কেউ Disposeস্কিল সংযোগ শনাক্তকরণ করতে পারে না যা ইতিমধ্যে সেট করা আছে null।
— ssd

10

কারণ SqlConnection, সংযোগের নিজস্ব দৃষ্টিভঙ্গি থেকে, তারা সমতুল্য। রিফ্লেক্টরের মতে, Dispose()কলগুলি Close()পাশাপাশি কয়েকটি অতিরিক্ত মেমরি-মুক্তকরণ অপারেশন করে - বেশিরভাগ সদস্যকে শূন্যের সমান করে by

স্ট্রিমের জন্য, তারা আসলে সমতুল্য। Stream.Dispose()কেবল ক্লোজ করুন ()।


1
তুমি কি নিশ্চিত? এমএসডিএন বলছে এটি উত্তরাধিকার সূত্রে প্রাপ্ত হয়েছেComponent যা থেকে চেষ্টা করার জন্য এবং কল করার জন্য কিছু করার মনে হয় নাClose() । আমি এই কোথাও কোথাও দেখতে পাচ্ছি না DBConnectionবা SqlConnectionসেই বিজ্ঞপ্তির কোনওটির সাথেই তার সম্পর্ক রয়েছে। তবে এটিতে এমন একটি ব্যক্তিগত রয়েছে DisposeMe()যা কোথাও উল্লেখ করা হয়নি ।
— Deanna

@ ডিয়ান্না এটি এখানে ওভাররাইড করা হয়েছে: github.com/dotnet/corefx/blob/…
— ডেভিড কম্পস

@ ডেভিডকম্পস এটি মন্তব্যটি লেখার পর থেকে 4 বছর পরে এটি পরিবর্তিত হয়েছে বলে মনে হয়। আমার লিঙ্কগুলি আর বৈধ নয়।
— ডান্না


6

এই দ্রুত পরামর্শটি দীর্ঘ উত্তর হয়ে উঠেছে। দুঃখিত।

টাইলার যেমন তার উত্তরের উত্তরে উল্লেখ করেছেন, কল Dispose()করা একটি দুর্দান্ত প্রোগ্রামিং অনুশীলন। কারণ এই পদ্ধতিটি সমস্ত সংস্থান-মুক্ত করার প্রয়োজনে "একসাথে সমাবেশ" করার কথা ছিল যাতে কোনও অনিবন্ধিত মুক্ত সংস্থান নেই। উদাহরণস্বরূপ, আপনি যদি কোনও ফাইলে কিছু পাঠ্য লিখে থাকেন এবং ফাইলটি বন্ধ করতে ব্যর্থ হন (সংস্থানটি মুক্ত করুন), এটি উন্মুক্ত থাকবে এবং জিসি কাছাকাছি না আসা পর্যন্ত আপনার লেখাটি অন্য কেউ করতে সক্ষম হবে না সম্পন্ন.

এখন, কিছু ক্ষেত্রে আপনি যে শ্রেণীর সাথে কাজ করছেন তার মতো আরও নির্দিষ্ট করে "চূড়ান্তকরণ" পদ্ধতি থাকবে যা কোনভাবে StreamWriter.Close()ওভাররাইড করে TextWriter.Close()। প্রকৃতপক্ষে তারা পরিস্থিতিটির জন্য সাধারণত আরও উপযুক্ত! Close()উদাহরণস্বরূপ, একটি স্ট্রিমরাইটার বস্তুর আইংয়ের আগে স্ট্রিম এবং অন্তর্নিহিত এনকোডারকে ফ্লাশ করে Dispose()! শান্ত!

তবে, এমএসডিএন ব্রাউজ করার মাধ্যমে আপনি দেখতে পাবেন যে এমনকি মাইক্রোসফ্ট কখনও কখনও ক্লোজার এবং ডিসপোজারদের ভিড় দ্বারা বিভ্রান্ত হয়। এই ওয়েবপৃষ্ঠায় , উদাহরণস্বরূপ, কিছু উদাহরণগুলিকে Close()অন্তর্নিহিত হওয়ার আগে ডাকা হয়েছিল Dispose()( এটি বিবৃত কেন তা বুঝতে না পারলে বিবৃতি ব্যবহার করে দেখুন ) এবং বিশেষত একটিতে তারা এটিকে বিরক্ত করে না। কেন হবে? আমিও হতবাক হয়ে গেলাম।

আমি যে কারণটি অনুভব করেছি (এবং, আমি চাপ দিয়েছি, এটি মূল গবেষণা এবং আমি ভুল হলে অবশ্যই অবশ্যই খ্যাতি হারাতে পারি) এটি Close()ব্যর্থ হতে পারে, সম্পদ খোলা রেখে ব্যতিক্রমী ফলস্বরূপ, Dispose()অবশ্যই এগুলি মুক্ত করে দেবে । যে কারণে একটি Dispose()সর্বদা একটি Close()কলকে রক্ষা করা উচিত (শ্লেষের জন্য দুঃখিত)।

MyResource r = new MyResource();

try {
  r.Write(new Whatever());

  r.Close()
finally {
  r.Dispose();
}

এবং হ্যাঁ, আমি অনুমান করি যে মাইক্রোসফ্ট একটি উদাহরণে পিছলে গেছে। সম্ভবত সেই টাইমস্ট্যাম্পটি কখনও ফাইলটিতে ফ্লাশ হবে না।

আমি আগামীকাল আমার পুরানো কোড ঠিক করছি।

সম্পাদনা: দুঃখিত ব্রানন, আমি আপনার উত্তর সম্পর্কে মন্তব্য করতে পারি না, তবে আপনি কি নিশ্চিত যে Close()কোনও finallyব্লকে ফোন করা ভাল ধারণা ? আমার ধারণা এটি থেকে একটি ব্যতিক্রম সম্ভবত ব্লকের বাকী অংশগুলি নষ্ট করে দিতে পারে যার মধ্যে সম্ভবত গুরুত্বপূর্ণ ক্লিনআপ কোড থাকবে।

ব্র্যাননের জবাব দিন: দুর্দান্ত, Close()যখন এটি সত্যই প্রয়োজন তখন কল করতে ভুলবেন না (যেমন স্ট্রিমগুলির সাথে ডিল করার সময় - .NET এ এসকিউএল সংযোগগুলি সম্পর্কে খুব বেশি কিছু জানেন না)।


প্রকৃতপক্ষে, আমি কখনই ক্লোজ () বলি না, আমি কেবল ডিসপোজ () এবং 'ব্যবহার' নির্মাণটি সঠিক কাজটি করতে দিই । আপনি যদি ডিসপোজ কল করছেন না, তবে আপনাকে ব্যতিক্রম-নিরাপদ উপায়ে ক্লোজ করতে হবে। অবশেষে ব্লকে ব্যতিক্রম হ্যান্ডলিং যুক্ত করা ভাল ধারণা হতে পারে।
— ব্র্যানন

ঠিক আছে, আমার মন্তব্যগুলি বিশেষত স্কেলক্লিয়েন্টের পক্ষে ছিল। মুল বক্তব্যটি হল, আপনি যে ক্লাসগুলি ব্যবহার করছেন তা বুঝতে হবে to সর্বদা ডিসপোজ কল করা সঠিক উত্তর নয়।
— ব্র্যানন

2

আইডিসপোজেবল থেকে টাইপকাস্ট, এবং এটির কল কল নিষ্পত্তি। এটি "iDisposable.Dispose" বাস্তবায়ন হিসাবে কনফিগার করা যাই হোক না কেন, ফাংশনটির নাম নির্বিশেষে যে কোনও পদ্ধতিটি আহ্বান করবে।


"ফাংশনটির নাম দেওয়া হয়েছে" "নিষ্পত্তি করুন": সুতরাং আমরা প্রাথমিক প্রশ্নে ফিরে আসছি:}
— ব্যবহারকারিক 2864740

ফাংশনটি আবদ্ধ IDisposable.Dispose, তবে এর অর্থ এই নয় যে এটি নাম। মনে রাখবেন যে ভিবিএন-তে, একটি ফাংশন এমন একাধিক ইন্টারফেস সদস্যদের সাথে আবদ্ধ হতে পারে যে নামগুলির সাথে ফাংশনের সাথে সম্পর্কিত হতে হবে না।
— সুপারক্যাট

এর মতো কাস্ট করুন:using (myObj as IDisposable)
— ইউশা আলেয়াউব

2

সাধারণত আমরা ক্লোজ (), অ্যাওর্ট () এবং নিষ্পত্তি () এ সমস্যার মুখোমুখি হয়েছি তবে তাদের মধ্যে পার্থক্য আমাকে বলি।

1) অ্যাবোর্ট: - আমি এটি ব্যবহার করার পরামর্শ দেব না কারণ যখন ক্লাবকে ক্লায়েন্ট বলা হয় তখন সার্ভারটি না বলে সংযোগটি মুছে ফেলা হয় তাই সার্ভার কিছু সময়ের জন্য অপেক্ষা করবে (প্রায় 1 মিনিট)। আপনার যদি বাল্কের অনুরোধ থাকে তবে আপনি গর্ভপাত () ব্যবহার করতে পারবেন না কারণ এটি আপনার সীমিত সংযোগ পুলের জন্য সময় বেরিয়ে আসতে পারে।

2) ক্লোজ: - সংযোগটি বন্ধ করার জন্য ক্লোজ খুব ভাল উপায় কারণ সংযোগটি বন্ধ করার সময় এটি সার্ভারকে কল করবে এবং সার্ভারটিকেও সেই পাশ দিয়ে বন্ধ করার স্বীকৃতি দেবে।

এখানে আরও একটি জিনিস দেখুন। কিছু ক্ষেত্রে, যদি ত্রুটি উত্পন্ন হয় তবে শেষ পর্যন্ত কোডটি লেখার পক্ষে ভাল উপায় নয় যে সংযোগটি বন্ধ করুন () কারণ সেই সময় যোগাযোগের ক্ষেত্রে ত্রুটিযুক্ত হবে।

3) নিষ্পত্তি: - এটি এক ধরণের কাছাকাছি তবে সংযোগ বন্ধ করার পরে আপনি এটি আর খুলতে পারবেন না।

সুতরাং এইভাবে চেষ্টা করুন,

private void CloseConnection(Client client)
    {
        if (client != null && client.State == CommunicationState.Opened)
        {
            client.Close();
        }
        else
        {
            client.Abort();
        }
    }

চেক অন client != nullভুল / বিভ্রান্তিকর কারণ এটি সমস্ত ব্যবহার রক্ষা করে না। এছাড়াও, আমি নিশ্চিত নই কীভাবে কোড "এই সংযোগটি খোলা নেই এবং এটি বন্ধ করা উচিত" অবস্থায় যেতে পারে।
— ব্যবহারকারী 2864740
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.