نمایش نتایج 1 تا 19 از 19

نام تاپیک: پیاده سازی تایمر با استفاده از Thread

  1. #1

    Smile پیاده سازی تایمر با استفاده از Thread

    با سلام به همه دوستان.
    یک سوال زیبا و جالب داشتم و اونم این سوال است که اگر شما از یک تایمر برای مثلا نمایش ساعت هر یک ثانیه یک بار در یک Label استفاده کنید می بینید در (Windows Task Manager) که با Ctrl+Alt+Del باز میشود در محل Performance قسمت Cpu Usage را مشاهده کنید خواهید دید که تنها 10% از Cpu را برای انجام محاسبات خود میگیرد .
    تا اینجا که مشکلی نسیت درست.
    اما مشکل از اینجا شروع میشود که اگر از یک Thread برای انجام نمایش ساعت در هر یک ثانیه استفاده کنم با کمال تعجب اون 10% قبلی به 100% تبدیل خواهد شد .
    حالا سوال من این است که تایمر از چه روشی برای محاسبات خود استفاده میکند و اگر میشود با یک کد مثلا همون مثال بالا را با یک Thread نمایش دهید فکر کنم که این سوال برای بسیاری از برنامه نویسان جالب باشد البته ممکن است خیلی از برنامه نویسان حرفه ای مثل شما دلیل و راه حل آن را بدانید ولی خیلی ها هم مثل من از این امر اطلاع ندارد و با پرسیدن یاد میگیرند .
    با سپاس و تشکر فراوان .

  2. #2
    کاربر دائمی آواتار newgoldenman
    تاریخ عضویت
    آبان 1385
    محل زندگی
    همشهري حضرت معصومه (س)
    پست
    367
    دوست عزیز مگر شما تایمرتان را خودتان نوشته اید؟!اگر چنین است که بعید میدونم، پیشنهاد میکنم از ابزار DateAndTimePicker استفاده کنید! که در این صورت CPU Usage شما هیچ تکانی نخواهد خورد(نسبت به وضع جاری)!

  3. #3
    نه این فقط یک مثال بود و منظور اصلی من چیز دیگری است .
    منظورم این بود که عمکرد تایمر تا اونجایی که من میدونم مثل یک Thread است یعنی در عین جدا بودن از برنامه (به صورت موزای چک نمودن زمان تنظیم شده برای انجام یک کد و بدون ایجاد هیچ اختلالی در برنامه تا رسیدن به زمان مورد نظر) کار چک نمودن زمان وارد شده در Interval تایمر که بر حسب میلی ثانیه مثلا 1000 میلی ثانیه یک بار است .
    خوب اگر که قرار باشد ما یک تایمر را با Thread درست کنیم به شکل زیر عمل میکردیم :
    1-یک if را تا زمان رسیدن به زمان یک ثانیه چک کنیم (در حد ساده ساعت سیستم را چک کنیم اگر تغییر کرد if دستوراتش را اجرا کند .)
    2-یک دستور خاص را انجام دهیم
    و این Thread تا آخر برنامه در حال انجام محاسبات فوق است .
    در حد ساده این طوری میشه درسته .
    حالا CPU Usage تایمر ما با تایمر خود #C خیلی متفاوته و سوال من هم همین جاست که چطوری میشه که این دو اینقدر متفاوت عمل میکنند و روی CPU تاثیرات متفاوتی را دارند . مگر تایمر خود #C در مورد همین مثال چطوری کد نویسی شده است
    حالا خودتون میتونید هر مثال دیگری رو طرح کنید و آزمایش نمایید تقریبا تمام تردهایی که مینویسید CPU Usage را در وضعیت 100% خواهد داد .
    جواب به این سوال میتواند به کاربران در ایجاد برنامه های قوی و در عین حال بهینه شده کمک نماید.
    ( داخل پرانتز یه مثال متفاوت را مطرح میکنم تا هدف از طرح این سوال را بهتر متوجه شوید تقریبا همه شما با برنامه های ضبط صدا آشنایی دارید این برنامه ها برای ضبط صدا باید اطلاعات کارت صوتی را در هر ثانیه مثلا 20000 بار در ثانیه نمونه برداری میکنند حالا پیاه سازی این برنامه با یک تایمر تقریبا غیر ممکن است و شما مجبور به استفاده از Thread هستید که با این کار دوباره مشکلات قبلی مطرح شده تکرار میشود . (این هم فقط یک مثال است)
    جالب اینجاست که برنامه های ضبط صدا با حداکثر 40% CPU Usage این کار را حتی با نمونه برداری های بالاتر در حدود 115000 نمونه برداری در ثانیه انجام میدهند و اینقدر کارآیی CPU را پایین نمی آورند)
    روش اینگونه برنامه ها به چه صورت است لطفا اگر میشود با یک کد توضیح دهید .
    ممنون

  4. #4
    لطفا یکی بیاد وسط و راهنمایی کنه .

  5. #5
    می تونید ترد رو با استفاده از دستور System.Threading.CurrentThread.Sleep() بخوابونید به مدت زمان مورد نظرتون. (اگر آدرس متد رو اشتباه تایپ کرده باشم می تونید با استفاده از Object Browser اون رو پیدا کنید)

  6. #6
    کاربر دائمی آواتار ARA
    تاریخ عضویت
    آبان 1383
    محل زندگی
    Bad Sector
    پست
    448

    Cool

    چون private message زده بودی برام برای اینکه جوابت رو بدم یک مثال آماده کرده بودم ولی وقتی که میخواستم update کنم دیدم اقای احمدی لپ کلام رو گفتن ممنون ولی خوب بگذار کاملتر جوابت رو بگیری
    اول روش خودت
    به مثال زیر نگاه کن

    long j = 0;
    privatevoid button2_Click(object sender, EventArgs e)
    {
    Thread thread1 = newThread(showClock);
    thread1.Start();
    Thread.Sleep(1000);
    thread1.Abort();
    label2.Text = j.ToString();
    }
    privatevoid showClock()
    {
    while (true)
    j++;
    }




    یک ترد فعال شده و داخل حلقه این کارها را تکرار میکند
    یک مقایسه و یک افزایش تا زمانی که این ترد را abort کنیم
    و در قسمت اصلی زمانی که thread1 فعال شده ترد اصلی sleep شده به مدت یک ثانیه و بعد از یک ثانیه فعال شده thread1 رو از بین برده و شماره j را به ما نشان میدهد
    به نظر شما چند مقایسه و افزایش رخ داده
    در سیستم من حدود celeron 1.7 GH عدد j=97,695,356 یعنی در برنامه ای که شما نوشتین در 1 ثانیه اینقدر کار انجام شده توسط cpu داریم


    حال به این نگاه کن

    privatevoid button2_Click(object sender, EventArgs e)
    {
    Thread thread1 = newThread(showClock);
    thread1.Start();
    }
    privatevoid showClock()
    {
    while (true)
    {
    Thread.Sleep(1);
    labelwriter(
    DateTime.Now.TimeOfDay);
    }
    }
    delegatevoidLableWriterDelegate(TimeSpan time);
    publicvoid labelwriter(TimeSpan time)
    {
    LableWriterDelegate sb = newLableWriterDelegate(lableUpdate);
    object[] args = newobject[1];
    args[0] = time;
    this.label2.Invoke(sb, args);
    }
    publicvoid lableUpdate(TimeSpan time)
    {
    label2.Text = time.ToString();
    }


    1000 بار در ثانیه lable2 رو update میکنیم ولی cpu usage من 5% رو نشون میده امتحانش کن حالا فهمیدی چرا سی پی یوت آمپر چسبونده

  7. #7

    Smile

    قبل از هر چیز باید از مدیر محترم بخش و بخصوص آقای ARA تشکر و قدر دانی ویژه نمایم که این قدر با حوصله پاسخ داده اند .
    اما .................
    تا اینجا که اگر خواسته باشیم تایمر را پیاده سازی کنیم کاملا عالی جواب میدهد ولی زمان Sleep بر حسب میلی ثانیه است یعنی اگر عدد 1 را وارد کنیم خواهیم دید که در هر ثانیه دستورات 1000 بار اجرا میشود .
    و اگر 1000 را برای Sleep وارد کنیم در هر ثانیه 1 بار اجرا میشود . تا اینجا را خوب فهیمدم .
    اما اگر خواسته باشیم مثلا نمونه برداری از کارت صوتی را در هر ثانیه مثلا 44100 بار در ثانیه برای فرمت MP3 داشته باشیم باید فواصل نمونه برداری منظم باشد و دقیقا همان تعداد را در ثانیه نمونه برداری کنیم .
    حال اگر Sleep را روی یک قرار دهیم در هر ثانیه فقط 1000 نمونه برداری را داریم . در حالی که ما میخواهیم 44100 بار در ثانیه را داشته باشیم اگر به این سوال هم جواب بدین خیلی از شما ممنون میشم .
    (به جای مثال نمونه برداری میتونیم یک متغییر را مثلا i را طوری در یک ثانیه ++i کند که در پایان یک ثانیه مقدار آن 44100 باشد )
    باز هم از تمامی عزیزانی که مرا راهنمایی کرده اند کمال تشکر را دارم .

  8. #8
    اگر با صوت کار میکنید:
    sampling یه کار سخت افزاریه ، کاری که شما دنبالشی Quantization هستش که یک کار نرم افزاریه و تایمر و امثالهم نیازی نداره!

    سخت افزار با یک دقتی(Sampling Rate) صدا رو از آنالوگ به دیجیتال تبدیل میکنه ،

    بعدا وقتی شما می خواهید این نمونه ها (Samples) رو با دقت های مختلف در فرمت های مختلف ذخیره کنید به روش Quantization دقت نمونه ها (Samples) رو تغییر میدید!

  9. #9
    کاربر دائمی آواتار hdv212
    تاریخ عضویت
    آبان 1384
    محل زندگی
    قم
    پست
    1,727
    ممکنه صریحا بگید شما دنبال چی هستید ؟ با توجه به نوشته هاتون شما بهتره از کامپوننت هایی که برای کار با صدا طراحی شده اند استفاده کنید، یکی از دلایل بالا بودن CPU Usage در مثال شما، نوع الگوریتم اجرایه، دقت کنید که در اگر CpuUsage خیلی زیاده، ولی معمولا پردازنده ها HyperThreading هستند و میتونن در آن واحد چندین رشته رو با هم اجرا کنن، باز اگه هدفتون رو بیشتر روشن کنید، شاید بتونم کمکتون کنم.

  10. #10
    باز هم سلام .
    بعضی از دوستان سوال کرده بودند که هدف از طرح این سوال چه بوده است هدف اصلی از طرح این سوال افزایش آگاهی در زمینه Thread بوده است و دانستن علت اشکالات به وجود آمده همانطور که مطرح کره بودم ، که آقای ARA با مثال های خوب خود به خوبی اشکالات من را در کد و بخصوص علت آن اشکال که اجرای بیش از حد دستورات در یک بازه زمانی بوده است را به بنده گوش زد کرده اند . و اطلاعات مرا در این زمینه بسیار بالا برده اند .
    طرح مثال نمونه برداری از کارت صوتی نیز فقط یک مثال بود و همین و بس همانطور که قبلا هم گفتم .

    (در صورتی که آقای hdv212 هم درست گفته باشند [ که معمولا پردازنده ها HyperThreading هستند] اما وقتی که کارمان با 40000 محاسبه در ثانیه راه می افتد چرا با تحقیقی که آقای ARA در مورد مثال تایمر در بالا انجام داه اند در حدود 98 میلیون محاسبه در ثانیه را به CPU تحمیل کنیم !!!! که این عدد در CPU های بالاتر قطعا عدد نجومی تری میشود
    - حالا یه لحظه خودتون را جای CPU بذارین ! )

    با این تفصیرات میخواستم گفته های آقای ARA را تکمیل تر کنید تا بدانم اگر خواسته باشم Sleep را در بازه زمانی معیین طوری تعیین کنیم که دستورات بیش از 1000 بار در ثانیه اجرا بشن مثلا 40000 بار در ثانیه و همون Cpu Usage قبلی را که بسیار بهینه بوده است را داشته باشیم چه کار باید بکنیم (بهینه سازی در استفاده از نرم افزار و سخت افزار) .
    که اگر به این سوال من هم جواب بدین دیگر مبحث Thread ها را با کمک شما دوستان تا اون سطحی که مورد قبول خودم باشه یاد گرفته ام و این تاپیک هم میتونه مرجع کاملی در رابطه با Thread برای سایر دوستانی که از Thread آگاهی ندارن و حتی موارد استفاده اون رو هم نمیدونن میتواند مفید باشد .

  11. #11
    دوست عزیز ،
    اگر نیاز به thread timer دارید، دات نت کلاس زیر را به صورت استاندارد دارد :
    System.Threading.Timer

  12. #12
    ببینید، این تردهایی که در .NET مشاهده می کنید رزولوشنی با دقت یک میلی ثانیه دارن، که از کلاک سیستم گرفته میشه. تا جایی که اطلاع دارم در ویندوز به صورت عادی نمی تونید رزولوشن این کلاک رو به مقداری کمتر از یک میلی ثانیه تغییر بدید، که البته با توجه به روشی که ویندوز با استفاده از اون ترد ها رو زمان بندی می کنه، حتی اگر بتونید هم این کار رو بکنید هیچ تضمینی نیست که تردها در زمان مورد نظر شما اجرا بشن.

    برای اینکه بتونید زمان این مورد رو به زیر یک میلی ثانیه تغییر بدید، می تونید از ران تایمهایی که می تونن در این زمینه کمک کنن استفاده کنید. توی ویندوز سیستم هایی مثل RTX وجود دارن که می تونن در پیاده سازی سیستمهای Soft RealTime (به گونه ای که اجرای دقیق ترد در زمان مشخص شده چندان اهمیت نداشته باشه) و یا Hard RealTime ( به گونه ای که ترد دقیقا در زمان مشخص شده اجرا بشه) به شما کمک کنن.

    این مدل سیستم ها می تونن دقتی به اندازه کلاک میکرو کنترولر 8254 رو به شما بدن، یعنی ضریبی از حدودا 800 نانو ثانیه (مقدار دقیقش رو نمی دونم). به این ترتیب برای مثال می تونید تردی داشته باشید که در هر 100 میکرو ثانیه اجرا بشه (بر حسب نوع کلاکی که استفاده می کنید). البته این موارد در .NET قابل استفاده نیست و فقط میشه پروسس مربوط به اون رو با استفاده از IPC به پروسس ایجاد شده در .NET مرتبط کرد تا به این ترتیب به مزیتهای هر دو دسترسی داشته باشید.

  13. #13
    حالا اگر دقیق هم در زمان مشخص شده نتونست اشکالی نداره ولی در همون حد و حدود هم اگر بود اشکالی نداره اگر میشه با کد توضیح بدین .

  14. #14
    در مورد سیستم های Hard RealTime در ویندوز NT می تونی اینجا رو ببینی

  15. #15
    با سلام خدمت مدیر محترم بخش .
    ممنون از راهنمایی های سازنده شما ولی توی سایتی که معرفی کردین اطلاعاتی بیشتر از آنچه که شما به صورت فارسی توضیح دادین نتونستم به دست بیارم (بیشتر در حد تئوری ) ولی برای من که تازه قدم در راه برنامه نویسی گذاشته ام قابل فهم برای پیاده سازی عملی نبود لطفا اگه میشه با یک مثال عملی شما و یا سایر دوستان یک تیر خلاص به این تاپیک بزنید .

  16. #16
    کاربر دائمی آواتار ARA
    تاریخ عضویت
    آبان 1383
    محل زندگی
    Bad Sector
    پست
    448
    سلام

    ببینید اونجوری که شما میخواین یک برنامه multithread میتونه کمکتون کنه

    thread pool هم گزینه خوبیه اگه کارها کوچک باشند مثل یک نمونه برداری و ذخیره آن
    فقط فکر کنم هماهنگ کردنشون یک کم دردسر باشه
    که اونهم از
    AutoResetEvent
    مربوط به thread ها میتوان کمک گرفت و همچنین مبحث قفل گذاری ها بشه حلش کرد

  17. #17
    دوست عزیز،
    مشکل ایشون تنظیم ترد به گونه ای هست که در هر ثانیه بیش از 1000 بار اجرا بشه، یعنی مقدار Sleep رو کوچکتر از یک میلی ثانیه وارد کنن.

    من اینن کار رو در .NET انجام ندادم، تا جایی هم که من می دونم به سادگی فراخوانی یک تابع و پاس کردن یک سری پارامتر نیست، بهتره لینکی که دادم رو به دقت مطالعه کنید، یه مقدار هم روی اینترنت بگردید، می تونید اطلاعات بیشتری بدست بیارید.

    موفق باشید

  18. #18
    کاربر دائمی آواتار PC2st
    تاریخ عضویت
    آذر 1385
    محل زندگی
    کرمانشاه
    سن
    38
    پست
    1,491
    در تکمیل گفته های آقای احمدی، برای توقف با دقتی در حد نانو ثانیه (دقیقا نمیدونم ولی خودش نوشته
    100-nanoseconds unit
    )، میشه به شکل زیر عمل کرد:

    Thread.Sleep( new TimeSpan( yourTime ) );

    yourTime زمانی هست که میخوای متوقف باشه (فکر کنم با دقت 100 نانو ثانیه باشه)

  19. #19
    کاربر دائمی آواتار ARA
    تاریخ عضویت
    آبان 1383
    محل زندگی
    Bad Sector
    پست
    448

    Cool

    منهم منظورش رو گرفتم
    به همین خاطر پیشنهاد مولتی ترد دادم که اگه ده ترد به فاصله های زمانی کمتر از 1 میلی ثانیه با هم اجرا بشند میشه رقم کمتری بدست آورد

    که البته


    نقل قول نوشته شده توسط omid_Ahmadi مشاهده تاپیک
    دوست عزیز،
    مشکل ایشون تنظیم ترد به گونه ای هست که در هر ثانیه بیش از 1000 بار اجرا بشه، یعنی مقدار Sleep رو کوچکتر از یک میلی ثانیه وارد کنن.

    با کمک دوست عزیزمون PC2st.ir فهمیدم راه دیگری نیز هست اتفاقا چک کردم بسیار جالب بود ممنون


    کد:
    Thread.Sleep( new TimeSpan( yourTime ) );
    yourTime زمانی هست که میخوای متوقف باشه (فکر کنم با دقت 100 نانو ثانیه باشه)

تاپیک های مشابه

  1. اجرای تابع با پارامتر به صورت یک Thread.
    نوشته شده توسط hdv212 در بخش C#‎‎
    پاسخ: 16
    آخرین پست: یک شنبه 17 خرداد 1394, 00:11 صبح
  2. ایجاد thread
    نوشته شده توسط mahtab_18 در بخش C#‎‎
    پاسخ: 1
    آخرین پست: سه شنبه 11 اردیبهشت 1386, 09:59 صبح

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •