বিভিন্ন থ্রেড নিক্ষেপ করা ব্যতিক্রম ধরা


109

আমার একটি পদ্ধতি ( Method1) একটি নতুন থ্রেড তৈরি করে। এই থ্রেডটি একটি পদ্ধতি চালায় ( Method2) এবং এক্সটেকশনের সময় একটি ব্যতিক্রম ছুঁড়ে ফেলা হয়। কলিং পদ্ধতিতে আমার সেই ব্যতিক্রম তথ্যটি পাওয়া দরকার ( Method1)

এটি কি আপনি সেখানে আমি এই ব্যতিক্রম ধরতে পারে someway Method1যে ফেলে দেওয়া হয় Method2?

উত্তর:


181

ইন .NET 4 এবং উপরোক্ত, আপনি ব্যবহার করতে পারেন Task<T>নতুন থ্রেড তৈরি করার পরিবর্তে বর্গ। তারপরে আপনি .Exceptionsনিজের টাস্ক অবজেক্টে সম্পত্তি ব্যবহার করে ব্যতিক্রম পেতে পারেন । এটি করার 2 টি উপায় রয়েছে:

  1. একটি পৃথক পদ্ধতিতে: // আপনি কিছু টাস্কের থ্রেডে ব্যতিক্রম প্রক্রিয়া করেন

    class Program
    {
        static void Main(string[] args)
        {
            Task<int> task = new Task<int>(Test);
            task.ContinueWith(ExceptionHandler, TaskContinuationOptions.OnlyOnFaulted);
            task.Start();
            Console.ReadLine();
        }
    
        static int Test()
        {
            throw new Exception();
        }
    
        static void ExceptionHandler(Task<int> task)
        {
            var exception = task.Exception;
            Console.WriteLine(exception);
        }
    }
  2. একই পদ্ধতিতে: // আপনি কলারের থ্রেডে ব্যতিক্রম প্রক্রিয়া করেন

    class Program
    {
        static void Main(string[] args)
        {
            Task<int> task = new Task<int>(Test);
            task.Start();
    
            try
            {
                task.Wait();
            }
            catch (AggregateException ex)
            {
                Console.WriteLine(ex);    
            }
    
            Console.ReadLine();
        }
    
        static int Test()
        {
            throw new Exception();
        }
    }

আপনি যে ব্যতিক্রম পাবেন তা নোট করুন AggregateException। সমস্ত বাস্তব ব্যতিক্রম ex.InnerExceptionsসম্পত্তি মাধ্যমে উপলব্ধ ।

ইন .NET 3.5 আপনাকে নিম্নলিখিত কোড ব্যবহার করতে পারেন:

  1. // আপনি সন্তানের থ্রেড ব্যতিক্রম প্রক্রিয়া

    class Program
    {
        static void Main(string[] args)
        {
            Exception exception = null;
            Thread thread = new Thread(() => SafeExecute(() => Test(0, 0), Handler));
            thread.Start();            
    
            Console.ReadLine();
        }
    
        private static void Handler(Exception exception)
        {        
            Console.WriteLine(exception);
        }
    
        private static void SafeExecute(Action test, Action<Exception> handler)
        {
            try
            {
                test.Invoke();
            }
            catch (Exception ex)
            {
                Handler(ex);
            }
        }
    
        static void Test(int a, int b)
        {
            throw new Exception();
        }
    }
  2. বা // আপনি কলারের থ্রেডে ব্যতিক্রম প্রক্রিয়া করছেন

    class Program
    {
        static void Main(string[] args)
        {
            Exception exception = null;
            Thread thread = new Thread(() => SafeExecute(() => Test(0, 0), out exception));
    
            thread.Start();            
    
            thread.Join();
    
            Console.WriteLine(exception);    
    
            Console.ReadLine();
        }
    
        private static void SafeExecute(Action test, out Exception exception)
        {
            exception = null;
    
            try
            {
                test.Invoke();
            }
            catch (Exception ex)
            {
                exception = ex;
            }
        }
    
        static void Test(int a, int b)
        {
            throw new Exception();
        }
    }

দুঃখিত তবে আমি উল্লেখ করতে ভুলে গেছি যে আমি .NET 3.5 ব্যবহার করছি। আমার বোঝা অনুসারে টাস্ক 4.0.০ জিনিস?
সিলভারলাইট স্টুডেন্ট

2
@ সিলভারলাইটস্টুডেন্ট ওকে, আপনার প্রয়োজনীয়তা মেটাতে আমি আমার উত্তরটি আপডেট করেছি।
অক্সিলিয়াম

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

2
@ সিলভারলাইটস্টুডেন্ট এই ক্ষেত্রে আমি পরিবর্তে একটি ল্যাম্বডা পাস করব Test। লাইক() => Test(myParameter1, myParameter2)
অক্সিলুমিন

2
@ সিলভারলাইটস্টুডেন্ট: আপডেট হয়েছে।
অক্সিলুমিন

9

আপনি মেথড 1 এ ব্যতিক্রমটি ধরতে পারবেন না। তবে, আপনি মেথড 2-এ ব্যতিক্রমটি ধরতে পারেন এবং এটিকে একটি চলকটিতে রেকর্ড করতে পারেন যা কার্যকর করার মূল থ্রেডটি তারপরে পড়তে এবং তার সাথে কাজ করতে পারে।


আপনার প্রতিক্রিয়ার জন্য ধন্যবাদ. সুতরাং যদি মেথড 1 ক্লাস 1 এর অংশ হয় এবং আমার কাছে সেই শ্রেণিতে ব্যতিক্রমের টাইপ রয়েছে। মেথড 2 যখনই একটি ব্যতিক্রম ছোঁড়ে তখন ক্লাস 1-এও এই ব্যতিক্রম পরিবর্তনশীল সেট করে। এটি কি ফর্সা ডিজাইনের মতো শোনাচ্ছে? এই পরিস্থিতিটি পরিচালনা করার জন্য কি কোনও সর্বোত্তম অনুশীলনের উপায় রয়েছে?
সিলভারলাইট স্টুডেন্ট

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

0

বিভিন্ন থ্রেডের মধ্যে ডেটা ভাগ করার সহজ পদ্ধতিটি shared dataনিম্নরূপ (কয়েকটি সিউডো কোড):

class MyThread
{
   public string SharedData;

   public void Worker()
   {
      ...lengthy action, infinite loop, etc...
      SharedData = "whatever";
      ...lengthy action...
      return;
   }
}

class Program
{
   static void Main()
   {
      MyThread m = new MyThread();
      Thread WorkerThread = new Thread(m.Worker);
      WorkerThread.Start();

      loop//or e.g. a Timer thread
      {
         f(m.SharedData);
      }
      return;
   }
}

মাল্টিথ্রেডিং সম্পর্কে এই দুর্দান্ত পরিচিতিতে আপনি এই পদ্ধতিটি পড়তে পারেন তবে, আমি এই বিষয়ে পড়তে পছন্দ করিO'Reilly book C# 3.0 in a nutshell বইয়ের নতুন সংস্করণটির মতো গুগল বইগুলিতেও অবাধে অ্যাক্সেসযোগ্য ভাই আলবাহারী (2007) দ্বারা এটি , কারণ এতে থ্রেড পুলিং, ফোরগ্রাউন্ড বনাম ব্যাকগ্রাউন্ড থ্রেড, ইত্যাদি ইত্যাদি সুন্দর এবং সাধারণ উদাহরণ কোড সহ অন্তর্ভুক্ত রয়েছে। (অস্বীকৃতি: আমি এই বইয়ের একটি জীর্ণ অনুলিপিটির মালিক)

আপনি যদি উইনফর্মস অ্যাপ্লিকেশনটি তৈরি করছেন তবে ভাগ করা ডেটা ব্যবহার বিশেষত সহজ, কারণ উইনফর্ম নিয়ন্ত্রণগুলি থ্রেড-নিরাপদ নয়। উইনফর্ম নিয়ন্ত্রণে কর্মী থ্রেড থেকে ডেটা পাস করার জন্য একটি কলব্যাক ব্যবহার করে মূল ইউআই থ্রেডকে Invoke()সেই নিয়ন্ত্রণের থ্রেড-নিরাপদ করতে কুরুচিপূর্ণ কোড দরকার । পরিবর্তে ভাগ করা ডেটা এবং একক থ্রেডযুক্ত 0.2 সেকেন্ডের System.Windows.Forms.Timerসংক্ষিপ্তসার Intervalব্যবহার করে আপনি সহজেই কর্মী থ্রেড থেকে নিয়ন্ত্রণ ছাড়াই তথ্য প্রেরণ করতে পারবেন Invoke


0

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

    public Boolean? Dance(String name) {

        // Already on an STA thread, so just go for it
        if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA) return DanceSTA(name);

        // Local variable to hold the caught exception until the caller can rethrow
        Exception lException = null;

        Boolean? lResult = null;

        // A gate to hold the calling thread until the called thread is done
        var lGate = new ManualResetEvent(false);

        var lThreadStart = new ThreadStart(() => {
            try {
                lResult = DanceSTA(name);
            } catch (Exception ex) {
                lException = ex;
            }
            lGate.Set();
        });

        var lThread = new Thread(lThreadStart);
        lThread.SetApartmentState(ApartmentState.STA);
        lThread.Start();

        lGate.WaitOne();

        if (lException != null) throw lException;

        return lResult;
    }

    public Boolean? DanceSTA(String name) { ... }

এটি যেমন হয় তেমন কোডের সরাসরি পেস্ট। অন্যান্য ব্যবহারের জন্য আমি একটি পরামিতি হিসাবে একটি ক্রিয়া বা ফাংশন সরবরাহ করার এবং থ্রেডে ডাকার পদ্ধতিটিকে হার্ড-কোডিংয়ের পরিবর্তে অনুরোধ করার পরামর্শ দেব।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.