PDA

View Full Version : گفتگو: کمک درباره برنامه Multi Thread در اکسس



sajjad_kochekian
یک شنبه 15 بهمن 1391, 21:39 عصر
سلام
من خیلی وقت بود دنبال این بودم که وقتی حجم عملیات برنامه زیاد میشه و فرم ها قفل میشه
بشه اون عملیات رو لغو یا درصد پیشرفت آن را مشاهده کرد

برای اینکار لازمه که از Thread استفاده کرد که ابن کار در برنامه مثل C# خیلی راحت انجام میشه ولی در اکسس کمی مشکل تر است.
البته یک منبع خوب پیدا کردم ولی ظاهرا مشکلاتی دارد.
دوستان لطفا یه نگاهی بیاندازند و روش استفاده از آن را اگر متوجه شدید, روش آن را بگید که ما هم استفاده کنیم.
با تشکر
http://bytes.com/topic/access/answers/882407-multi-threading

mazoolagh
دوشنبه 16 بهمن 1391, 13:23 عصر
(تا اونجایی که میدونم!) همچین خلاصه بگم اینکار شدنی نیست چون ذات آفیس این قابلیت رو نداره. کل اپلیکیشن اکسس یک thread هست و اگر هم کدی دیدین که مدعی اینکار شده در واقع یک شبیه سازی هست و در واقعیت threadها رو همزمان اجرا نمیکنه. نهایتا هم یک چیز شکسته بسته ای هست که پایداری نداره.
اگر تایمر و doevents جوابگوی کار هست که هیچ در غیر اینصورت یا برنامه تون رو اصلاح کنین و یا تکنولوژی رو (دات نت)

sajjad_kochekian
پنج شنبه 19 بهمن 1391, 23:10 عصر
اگر تایمر و doevents جوابگوی کار هست که هیچ

در این مورد میشه بیشتر توضیح بدید
من آشنائی ندارم

mazoolagh
دوشنبه 23 بهمن 1391, 11:39 صبح
timer از رخدادهای فرم هست و میتونین با اون یک روتین رو در فواصل زمانی معین اجرا کنین

doevents در اصل یک تابع هست که کاری به مقداری که برمیگردونه نداریم ولی از این ویژگیش استفاده میکنیم که موقع اجرا کنترل رو به سیستم عامل برمیگردونه بنابراین در پروسه های وقت گیر کمک میکنه در حین اجرا بتونیم کارهای دیگه هم انجام بدیم یا پروسه رو کنسل کنیم.
فرضا یک رکوردست دارین و توسط حلقه یک سری پردازش روش انجام میدین و یک progress bar هم دارین که با هر بار اجرای حلقه مقدارش رو update میکنین. اگر از doevents استفاده نکنین ممکنه پیشرفت progress bar رو نبینین و همینطور نمیتونین از اجرای پروسه منصرف بشین.

sajjad_kochekian
دوشنبه 23 بهمن 1391, 20:25 عصر
میشه یک نمونه بگذارید

sajjad_kochekian
دوشنبه 23 بهمن 1391, 21:27 عصر
من DoEvent‌را به این روش تست کردم ولی سرعتش یکم پائینه

Private Sub Command2_Click()
Dim i, k As Long
Debug.Print Now
k = 10000
ProgressBar1.Max = k

For i = 1 To k
n = Now
ProgressBar1.value = i
DoEvents
' Debug.Print i
Next i
Debug.Print Now

End Sub

RESMAILY
دوشنبه 23 بهمن 1391, 22:03 عصر
به نام خدا
با سلام. با پوزش از دوستان محترم. من روشي را به اين شرح امتحان كردم كه موقع انجام عمليات روي پيشاني يا caption فرم مربوطه يا يك فرم كمكي "مثلا منتظر باشيد" و غيره، عدد ركورد مربوطه يا چيزي شبيه به آن را اعلام مي كنم. اين روش بدون بدون doevents هم پاسخ مي دهد. امتحان بفرماييد شايد اين روش به نوعي به دردتان بخورد و از سرعت كار هم كم نشود.

sajjad_kochekian
سه شنبه 24 بهمن 1391, 13:05 عصر
به نام خدا
با سلام. با پوزش از دوستان محترم. من روشي را به اين شرح امتحان كردم كه موقع انجام عمليات روي پيشاني يا caption فرم مربوطه يا يك فرم كمكي "مثلا منتظر باشيد" و غيره، عدد ركورد مربوطه يا چيزي شبيه به آن را اعلام مي كنم. اين روش بدون بدون doevents هم پاسخ مي دهد. امتحان بفرماييد شايد اين روش به نوعي به دردتان بخورد و از سرعت كار هم كم نشود.

اگر بخواهید عملیات را لغو کنید مشکلی نیست؟
اگر عملیات خیلی سنگین باشه چی؟
اگر می تونید یه نمونه بگذارید.

mazoolagh
سه شنبه 24 بهمن 1391, 13:30 عصر
مطمئنا سرعت پایینتر هست و در این مثال شما از یک کم هم بیشتره! (به همون دلایلی که توضیح داده شد) ولی وقتی progress bar استفاده میکنین بیشتر از 50 (حداکثر 100) گام عملا بیفایده است. باید یک حلقه دیگه هم داخل حلقه اصلی بگذارین که تعداد گام ها رو نرمال کنه و doevents رو در حلقه بیرونی بگذارین.

RESMAILY
سه شنبه 24 بهمن 1391, 21:42 عصر
به نام خدا
با سلام. قطعا عمليات را مي شود قطع كرد. ولي فكر كنم در هر برنامه راهكار مخصوص به خود را داشته باشد. چون لابد شما مي خواهيد مجددا برنامه را از نقطه متوقف شده ادامه هم بدهيد. لذا اينكه يك تابع يادستوري چيزي براي اين كار درون آكسس وجود داشته باشد (نداريم؟) ولي احتمالا در اغلب اوقات هر اقدامي براي توقف عمليات يك Error تلقي خواهد شد و گمانم بشود با يك ارجاع مناسب، در هنگام ارور برنامه به سمت يك ثبت و ربط عمليات و اعلام مشخصات باقيمانده هل داد.
امتحان كنيد آيا با تكمه Puse چه اتفاقي مي افتد. در ضمن الآن يادم افتاد كه dbEngine يك متد به نام idle دارد كه آن موقع ها مي گفتند براي يك چنين مواقعي است. امتحان نكردم ولي دوستان باتجربه مثل همين جناب Mozoolagh و يا اقاي اميري خوب تو كوك آكسس رفته اند و ممكن است يك راهنمايي همه مان را بكنند.

sajjad_kochekian
پنج شنبه 26 بهمن 1391, 21:02 عصر
Dim m As Boolean
Private Sub Command2_Click()
If m = True Then
Dim mg As Byte
mg = MsgBox("ÂíÇ ÚãáíÇÊ áÛæ ÔæÏ¿", vbYesNo, "åÔÏÇÑ")
If mg = vbYes Then
Exit Sub
End If
Else
Dim i, k As Long
Debug.Print Now
k = 10000
ProgressBar1.Max = k
Command2.Caption = "&Cancel"
For i = 1 To k
DoEvents

m = True
n = Now
ProgressBar1.value = i
Label3.Caption = i

' Debug.Print i
Next i
m = False

Debug.Print Now
Command2.Caption = "Do"
MsgBox "Ok"
End If
ex:
End Sub
من با این روش می خواستم از عملیات بیام بیرون ولی هنوز عملیات ادامه داشت
مرتبه اول که کلیک میشه شروع عملیات و تغییر عنوان دکمه به (لغو)
مرتبه دوم با کلیک می خواهد عملیات را لغو کند ولی جواب نمی ده

FastCode
پنج شنبه 26 بهمن 1391, 21:45 عصر
http://msdn.microsoft.com/en-us/library/ee191552.aspx

Abbas Amiri
جمعه 27 بهمن 1391, 01:40 صبح
سلام
همان طور که آقای اسماعیلی گفتند ،دستور DBEngine.Idle dbRefreshCache خصوصا برای محیطهای اکسس چندکاربره مفید است
ضمن اینکه در پست 8 شما از یک باتن درحالی که دررویداد Click آن هستید ، انتظار پاسخ به یک کلیک دیگر رانداشته باشید . حداقل از یک باتن دیگر استفاده کنید.

FastCode
جمعه 27 بهمن 1391, 02:25 صبح
سلام
همان طور که آقای اسماعیلی گفتند ،دستور DBEngine.Idle dbRefreshCache خصوصا برای محیطهای اکسس چندکاربره مفید است
ضمن اینکه در پست 8 شما از یک باتن درحالی که دررویداد Click آن هستید ، انتظار پاسخ به یک کلیک دیگر رانداشته باشید . حداقل از یک باتن دیگر استفاده کنید.
کاش حداقل لینک من رو میخوندید و اشتباه پست های قبلی رو تکرار نمیکردید.
در مورد EventLoop هم اگر جست و جو بکنید خیلی از ابهاماتتون رفع میشه

Abbas Amiri
جمعه 27 بهمن 1391, 14:12 عصر
کاش حداقل لینک من رو میخوندید و اشتباه پست های قبلی رو تکرار نمیکردید.
در مورد EventLoop هم اگر جست و جو بکنید خیلی از ابهاماتتون رفع میشه

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

FastCode
جمعه 27 بهمن 1391, 14:55 عصر
سلام
متاسفانه بنده به علت کمبود دانش در استفاده از کلاسهای دات نت فریم ورک ، درمحیط اکسس قادر به درک وانجام روش پیشنهادی شما نشدم .
متمنی است درمورد بحث فوق یک مثال عملی ساده در محیط اکسس ایجاد کنید تا برای امثال بنده درس جدیدی باشد.
پیشاپیش سپاسگزارم.
این مطلب خیلی مهمیه.و کاربردش فقط این نیست.خیلی جاها ممکنه به کارتون بیاد.
شبکه
فایل سیستم
پردازش موازی
NUMA
.....
سعی کنید بیشتر سعی کنید.چون من کلا از محصولات Microsoft استفاده نمیکنم نمیتونم در مورد مثال کمکتون کنم.

FastCode
شنبه 28 بهمن 1391, 11:06 صبح
تصور میکنم میبایست دقت میکردید که در تالار اکسس پستتون رو ارسال کردید , در واقع مطلب بی ارتباط به مبحث فعلی هستشوقتی C#‎ رو توی سوال دیدم بقیش رو نخوندم.:(
http://stackoverflow.com/questions/2898953/multi-thread-in-ms-access-async-processing

البته هنوز اشتباه بودن اون روش سر جاش هست.DoEvents همیشه اشتباهه.

FastCode
شنبه 28 بهمن 1391, 17:32 عصر
سلام FastCode

خوب با توجه به اينكه فروديد از محصولات Microsoft استفاده نميكنيد قاعدتا نميشه زياد وارد بحث شد ، مجدداً توجه شما رو جلب ميكنم كه در تالار اكسس هستيم و بر همين اساس هم در پاسخها ميبايست به فراخور اكسس و VBA مطالب رو درج كنيم
مطمئناً شما در خصوص مبحث اطلاعات كاملي داريد ولي اجازه بديد با نگارشي در خور تالار اكسس موضوع رو پيگيري كنيم
دستور DeEvents درست هستش ولي اينكه در اينجا مصداقي داره و يا نه وارد بحث نميشيم
اكسس يك سيستم تك پروسه اي هستش و اصطلاحاً دستورات رو به صورت سري ( پشت سر هم ) در حالت اجرا قرار ميده
در بين دستورات متوالي وقفه هايي به وجود مياد ؛ فرضا شما در حال تغيير يكسري اطلاعات هستيد ؛ اكسس مرتبا در بين پروسه هاي خواندن ، تغيير و نوشتن اطلاعات در حال شيفت كردن هستش
در بين هر دو پروسه ، شما زمان وقفه اي داريد كه اصطلاحاً به اون idle ميگيم ( زماني كه سيستم زير بار نيست ) ، كنترل idle‌ در سطح سيستم عامل اجرا ميشه
دستور DoEvents در واقع كنترل رو به سيستم عامل برميگردونه تا امكان وارد كردن يك دستور در بين پشته دستورات رو مهيا كنه ( به صورت Real Time )
در واقع سيستم عامل در اين بين بخش نقش ميانجي رو داره بازي ميكنه
به ظاهر به كمك دستور DoEvents ميشه چند وظيفه رو به صورت همزمان به انجام رسوند وليكن در واقع دستورات همچنان به صورت سري هستند و هر پروسه مستقل از ديگر پروسه هاي اجرايي هستش ، وليكن چون توسط اين دستور ميشه از زمانهاي بي كاري استفاده به عمل آورد ، اين شبه ايجاد ميشه كه كارها به صورت همزمان در حال اجرا هستند كه البته اينگونه نيست
در همون مثال Progressbar
شما چند تا ركورد رو به روز ميكنيد ؛ پروسه متوقف ميشه و Progressbar به روز رساني ميشه حال مجدداً همين سيكل از ابتدا به انجام ميرسه تا عمليات به انتها برسه در واقع در هر لحظه فقط يكي از اين دو كار
در هر صورت ايرادي به پيشنهاد دوستمون در خصوص استفاده از DoEvents در داخل محيط اكسس وارد نيست
فقط يك نكته وجود داره و اون هم پديده پيش / پس اجرايي هستش كه استفاده از DoEvents‌ رو الزاماً با نياز به برخي دقتهاي مظاعف همراه ميكنه تا مشكلي در پروسه ايجاد نشه
:.:.:.:.:.
موفق باشيد
سلام

من از ۱۰ سال پیش تا همین سه سال پیش با Access کار کردم و برنامه نوشتم.
فقط سه ساله که گزاشتمش کنار.احتمال دادم ممکنه بتونم کمک کنم.
هم تا حالا Event Loop نوشتم.هم Message Handler. هم میدونم Shared Memory و Lock و Wnd و DC و اینا چیه.
خیلی خوبه که شما توی محیط Access به این چیزها توجه میکنید.ولی لازم نیست به من یاد بدید.
در هر حالت DoEvents میتونه خطرناک باشه.و در کمترین حد خطر باعث ™StackOverFlow بشه.
حیف الان به هیچ ویندوزی دسترسی ندارم.اگر داشتم نمونه ۱۰خطیش رو براتون میزاشتم.

DoEvents هم Control رو یه سیستم عامل برنمیگردونه.
پیغام های سیستم عامل رو که منتظر اجرا شدن بودن رو اجرا میکنه.

FastCode
شنبه 28 بهمن 1391, 19:24 عصر
DoEvents ربطی به Multi-Thread بودن یا نبودن نداره.
به طور مثال وقتی DoEvents رو اجرا میکنید ممکنه کنترل دوباره با اول همون تابع برگرده.

امیدوارم Jeff Atwood از من معتبرتر باشه.
http://www.codinghorror.com/blog/2004/12/is-doevents-evil.html
http://www.codinghorror.com/blog/2005/08/is-doevents-evil-revisited.html

FastCode
شنبه 28 بهمن 1391, 22:00 عصر
Fast Code

ظاهراً شما اصلا دقت نمی کنید که اینجا تالار اکسس هستش و در زمره پلت فرم دات نت قرار نمیگیره

آخه چه ربطی به دات نت داره که دارید مقالات اون رو لینک میکنید

ظاهراً شما اصلا مطالب رو نمیخونید

حالا فرض کنید یک مطلب رو اشتباه نوشتید , پذیرش اشتباه اینقدر براتون سخته که دارید به در و دیوار میزنید و زمین و آسمون رو به هم می بافید

نوشتید نمیخواید بهتون چیزی یادبدم , اگر خواستید همینجا اعلام کنید تا به جای Jeff Atwood !! براتون توضیح بدم ( البته اگر قصد یادگیری دارید )



مگر کسی گفت داره , چرا تصورات خودتون رو به دیگران دارید نسبت میدید

:.:.:.

به هر حال صلاح کار خودتون رو خودتون میدونید

من تصور میکنم شما فرق بین محیطهای توسعه مبتی بر دات نت و اکسس رو نمی دونید چیه و همین امر موجب ایجاد اشکال شد

موفق باشید

این DoEvents تفاوتی با اون DoEvents نداره.
ولی اگر شما فکر میکنید تفاوت داره لطفا توضیح بدید.خوشحال میشم یاد بگیرم.

@OP
اگر بیشتر سعی کنید میتونید از Thread هم استفاده کنید.
شخصی که در این لینک سوال پرسیده چند تا اشتباه کرده.که مهمترینش بستن handle ه Thread بلافاصله بعد از ایجاد کردنشه.ولی بقیش قابل تحمله.
http://www.mrexcel.com/forum/excel-questions/237639-multi-threaded-visual-basic-applications-createthread.html

پ.ن.اصلا دوست ندارم برای یه سوال ویندوز نصب کنم.ولی ظاهرا باید ...

RESMAILY
شنبه 28 بهمن 1391, 22:10 عصر
به نام خدا
با سلام. با تشکر از دوستان و با اجازه آنها، بی آنکه بخواهم وارد معقولات این بحث شوم. مجددا فقط عرض می کنم که برای توقف این نمی دانم پروسس یا ترد و غیره، اگر حین عملیات، تکمه های کنترل + pause را فشار دهید عملیات متوقف و یک ارور (بدون شماره) می دهد که البته بنده هنوز تحقیق نکردم که چگونه می شود آن ارور را تحت کنترل درآورد و مثلا به روال دلخواه هدایتش نمود. ولی خواستم عرض کنم که ظاهرا می شود در عملیات بصورت دستی وقفه ایجاد کرد.البته این نکته تازه ای نیست و همه با عملکرد این تکمه حین آزمایش کدها اشنا هستند. ولی این کلید های ترکیبی پس از کامپایل برنامه یا تبدیل آن به فایل mde هم جواب می دهد. حال خود دانید! اگر از دوستان باتجربه کسی می تواند یقه آن ارور لاکردار (بقول بهرنگ!) را بگیرد، به ما هم بیاموزد.

FastCode
شنبه 28 بهمن 1391, 22:13 عصر
DoEvents passes control to the operating system. Control is....




:.:.
خب درست توضیح نداده.
وقتی DoEvents رو صدا میزنید.یه حلقه با این ساختار در UserSpace اجرا میشه

while(GetMessage(&Msg, NULL, 0, 0) > 0) { WNDPROC fWndProc = (WNDPROC)GetWindowLong(Msg.hwnd, GWL_WNDPROC); fWndProc(Msg.hwnd, Msg.message, Msg.wParam, Msg.lParam); }در تابع ProcessMessage پیغام ها با توجه با پارامتر msg شون دسته بندی میشن و به محل مورد نظر خودشون میرن hWnd
و دو مقدار hparamو lparam و یا مقادیری که بهش اشاره میشه رو به تابع شما میدن.
در واقع تنها جایی که کنترل از برنامه شما خارج میشه GetNextMessage و PendingMessageExists هستن که روی Stack شما تاثیری ندارن.
پس اگر DoEvents تابعی رو صدا بزنه که پیغامی ایجاد کنه که DoEvents ویغام رو به همون تابع بفرسته شما یک عدد StackOverFlow دارید.
من وقتی ۱۴ سالم بود همه ی این توابع رو خودم نوشتم و باهاش کار کردم.درسته ۶ سال گزشته ولی هنوز اینقدر یادم هست که بتونم یک Case ه خطا مثال بزنم.

Abbas Amiri
شنبه 28 بهمن 1391, 22:13 عصر
سلام

اینطور که معلومه دوستمون FastCode حداکثر 10 ساله بودند که کار بااکسس رو شروع کردند (سال 88 ایشون 19 سال داشتند و1کسس 97 حداکثر تا سال 2000 استفاده میشده)
با توجه به استعداد خارق العاده ایشان ، مطمئن هستم میتونند موضوع موردادعایشان رو ثابت کنند . باز هم از ایشان خواستار یک مثال عملی هستم .
با تشکر

FastCode
شنبه 28 بهمن 1391, 22:40 عصر
سلام FastCode

بحث با شما فایده نداره

بنده رو معذور بدونید و تصور کنید که حق با شماست و اطلاعاتی ندارم

اونهایی که می بایست متوجه موضوع بشن , مطمئنا شدند

موفق باشید
فقط ثابت کن اشتباه کردم.کار سختی نباید باشه.

Counter-Reference از همون سایت
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644928%28v=vs.85%29.aspx
اونجایی که مرجع شما گفته کنترل به سیستم عامل برمیگرده ربطی به برنامه ما نداره.اونجایی ربط داره که همون ترد با همون stack دو باره همون تابع رو صدا میزنه




اینطور که معلومه دوستمون FastCode حداکثر 10 ساله بودند که کار بااکسس رو شروع کردند (سال 88 ایشون 19 سال داشتند و1کسس 97 حداکثر تا سال 2000 استفاده میشده)
با توجه به استعداد خارق العاده ایشان ، مطمئن هستم میتونند موضوع موردادعایشان رو ثابت کنند . باز هم از ایشان خواستار یک مثال عملی هستم .
با تشکر چطوری حساب کردی؟
الان ۱۹ سالمه.

FastCode
شنبه 28 بهمن 1391, 23:39 عصر
اگر اینقدر مثال عملی مخواهید میتونید یک تایمر درست کنید.
Interval رو مساوی 100 قرار بدید.
این کد رو در Timer بنویسید
Sleep 200
DoEvents
میبینید که برنامتون بعد از چند دقیقه منفجر میشه.

این API رو هم اضافه کنید.
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
اگر فکر میکنید استفاده از API برای مثال خوب نیست میتونید یک حلقه خالی بنویسید که بیشتر از ۱دهم ثانیه طول بکشه.نه کمتر.
اگر از پردازنده هایی مثل Intel Core i5/7 استفاده میکنید بهتره که حلقه رو طولانی تر بنویسید که Turbo Boost باعث خراب شدن مثال نشه.

Abbas Amiri
یک شنبه 29 بهمن 1391, 00:32 صبح
اگر اینقدر مثال عملی مخواهید میتونید یک تایمر درست کنید.
Interval رو مساوی 100 قرار بدید.
این کد رو در Timer بنویسید
....................
سلام
ممنون ازپاسختون ولی منظورم :

اگر بیشتر سعی کنید میتونید از Thread هم استفاده کنید.بود

FastCode
یک شنبه 29 بهمن 1391, 01:53 صبح
سلام
ممنون ازپاسختون ولی منظورم :
بود
این یکی رو واقعا شرمندم چون Office ندارم.خیلی دوست داشتم میتونستم کمکتون کنم.

sajjad_kochekian
سه شنبه 08 اسفند 1391, 21:51 عصر
بابا من یکم کمک خواستم چرا همیشه عادت دارید به هم دیگه گیر بدید