mr.sirwan
شنبه 22 آذر 1399, 22:57 عصر
سلام و درود
دوستان بنده میخوام موقع اجرای دستورات دیتابیس، یه فرم با پراگرس بار داخلش نمایش بدم بصورت Marquee و اصلا روند و درصد پیشرفت برام مهم نیست چون اصلا درصد پیشرفت قابل اندازه گیری نیست. روش های زیادی با استفاده از backgroundworker وجود داره ولی من نمیخوام توی تمامی متدهام بیام و بکگران ورکر نیو کنم و متد یا دستوراتم رو به DoWork پاس بدم، من یه چیز خیلی راحت و ساده میخوام که داخل بدنه متدهام، ابتدای هر متد یه فانکشنی صدا بزنم که بیاد و پراگرس بار رو برای کاربر نمایش بده و در پایان متدها یه فانکشن دیگه ای صدا بزنم که کارش بستن فرم پراگرس بار هستش
حالا برای اینکار من اومدم یه کلاس تعریف کردم به این شکل:
public static class LoadingProgress
{
private static Thread _LoadingScreenThread;
private static LoadingForm _ls;
private static bool _shown = false;
private static Form _parent;
public static void ShowLoadingScreen(Form parent = null)
{
_parent = parent;
Initiate();
}
private static void Initiate()
{
if (_LoadingScreenThread == null)
{
_LoadingScreenThread = new Thread(new ThreadStart(DoShowLoadingScreen));
_LoadingScreenThread.SetApartmentState(ApartmentSt ate.STA);
_LoadingScreenThread.IsBackground = true;
_LoadingScreenThread.Start();
}
}
public static void CloseLoadingScreen()
{
//Thread.Sleep(50);
if (_ls != null && _ls.InvokeRequired)
{
_ls.Invoke(new MethodInvoker(CloseLoadingScreen));
}
else
{
if (_shown)
{
_shown = false;
Application.ExitThread();
}
try
{
if (_LoadingScreenThread != null)
_LoadingScreenThread.Interrupt();
ActivateParentForm();
_ls?.Close();
_ls?.Dispose();
_LoadingScreenThread = null;
}
catch
{ }
}
}
private static void ActivateParentForm()
{
if (_parent != null)
{
if (_parent.InvokeRequired)
_parent.Invoke(new Action(() =>
{
_parent.Activate();
}));
else
_parent.Activate();
}
}
private static void DoShowLoadingScreen()
{
_ls = new LoadingForm();
_shown = true;
try
{
_ls.TopMost = true;
_ls.ShowDialog();
}
catch
{
}
}
}
همونطور که معلومه داخل کلاس یه ترد ایجاد میشه برای نمایش فرم پراگرس بار، این کلاس تا حدودی کار منو راه مینداخت حالا بماند که یکسری مشکلات و ارور ها هم میده حین اجرا ولی به خاطر همون ارور ها، بخش catch مربوط به try هارو خالی گذاشتم و هیچ اکسپشنی ازشون دریافت نمیکنم، اما همین امروز شروع کرد داخل دیباگر خود ویژوال ستودیو یه سری ارورهارو بهم نمایش دادن، که دوتاشونو میذارم. البته ناگفته نماند که این ارور ها فقط داخل دیباگر و در حالت دبیاگ بهم نمایش داده میشن و UI برنامه و خود فرم پراگرس بار، به مراتب داره کندتر میشه تا جایی که ارور رو بهم نمایش میده ولی توی حالت ریلیز گویا مشکلی وجود نداره و برنامه هم با کندی مواجه نمیشه.
اینم ارورهایی که میگیرم:
ارور اول:
Managed Debugging Assistant 'DisconnectedContext' : 'Transition into COM context 0x1a36328 for this RuntimeCallableWrapper failed with the following error: The callee (server [not server application]) is not available and disappeared; all connections are invalid. The call did not execute. (Exception from HRESULT: 0x80010012 (RPC_E_SERVER_DIED_DNE)). This is typically because the COM context 0x1a36328 where this RuntimeCallableWrapper was created has been disconnected or it is busy doing something else. Releasing the interfaces from the current COM context (COM context 0x1a36270). This may cause corruption or data loss. To avoid this problem, please ensure that all COM contexts/apartments/threads stay alive and are available for context transition, until the application is completely done with the RuntimeCallableWrappers that represents COM components that live inside them.'
ارور دوم:
Managed Debugging Assistant 'ContextSwitchDeadlock' : 'The CLR has been unable to transition from COM context 0x20692f8 to COM context 0x20693b0 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.'
حالا در رابطه با ارور ها میدونم داره از طولانی شدن یه عملیاتی شکایت میکنه ولی نمیدونم و نمیتونم بفهمم که چه عملیاتیه که طولانی هست، چون واقعیتش من اصلا عملیات انچنانی انجام نمیدم، فقط سلکت توسط دستورات Linq هستش، و داخل پروفایلر اس کیو ال که نگاه میکنم ببینم کوئری های اضافه ای اجرا نشن، خیر هیچ کوئری اضافه ای اجرا نمیشه و هر کوئری کمتر از 0.5 ثانیه و طولانیترینشون 1.5 ثانیه طول میکشه اجرا بشه، خب حالا که مشکلی از طرف دستورات اس کیو ال نیست، پس به این نتیجه میرسم که مشکل از خود پراگرس بار و مربوط به تردی هستش که داخلش وجود داره
حالا چندتا سوال:
1. چون در حالت ریلیز این ارور ها وجود ندارن و مشکلی هم ظاهرا از بابت کندی سرعت پیش نمیاد، آیا این مشکل رو بذارم همینجوری بمونه و نیازی نیست برطرفش کنم؟
2. آیا این روش نمایش پراگرس بار روش خوب و بهینه تری داره؟ شاید باور نکنید ولی دغدغه این پراگرس بار به اندازه کل این نرم افزاره منو پیر کرده
اگر کسی در این رابطه و این مشکل تجربه ای داره و تونسته حلش کنه لطفا راهنمایی بفرمایید
دوستان بنده میخوام موقع اجرای دستورات دیتابیس، یه فرم با پراگرس بار داخلش نمایش بدم بصورت Marquee و اصلا روند و درصد پیشرفت برام مهم نیست چون اصلا درصد پیشرفت قابل اندازه گیری نیست. روش های زیادی با استفاده از backgroundworker وجود داره ولی من نمیخوام توی تمامی متدهام بیام و بکگران ورکر نیو کنم و متد یا دستوراتم رو به DoWork پاس بدم، من یه چیز خیلی راحت و ساده میخوام که داخل بدنه متدهام، ابتدای هر متد یه فانکشنی صدا بزنم که بیاد و پراگرس بار رو برای کاربر نمایش بده و در پایان متدها یه فانکشن دیگه ای صدا بزنم که کارش بستن فرم پراگرس بار هستش
حالا برای اینکار من اومدم یه کلاس تعریف کردم به این شکل:
public static class LoadingProgress
{
private static Thread _LoadingScreenThread;
private static LoadingForm _ls;
private static bool _shown = false;
private static Form _parent;
public static void ShowLoadingScreen(Form parent = null)
{
_parent = parent;
Initiate();
}
private static void Initiate()
{
if (_LoadingScreenThread == null)
{
_LoadingScreenThread = new Thread(new ThreadStart(DoShowLoadingScreen));
_LoadingScreenThread.SetApartmentState(ApartmentSt ate.STA);
_LoadingScreenThread.IsBackground = true;
_LoadingScreenThread.Start();
}
}
public static void CloseLoadingScreen()
{
//Thread.Sleep(50);
if (_ls != null && _ls.InvokeRequired)
{
_ls.Invoke(new MethodInvoker(CloseLoadingScreen));
}
else
{
if (_shown)
{
_shown = false;
Application.ExitThread();
}
try
{
if (_LoadingScreenThread != null)
_LoadingScreenThread.Interrupt();
ActivateParentForm();
_ls?.Close();
_ls?.Dispose();
_LoadingScreenThread = null;
}
catch
{ }
}
}
private static void ActivateParentForm()
{
if (_parent != null)
{
if (_parent.InvokeRequired)
_parent.Invoke(new Action(() =>
{
_parent.Activate();
}));
else
_parent.Activate();
}
}
private static void DoShowLoadingScreen()
{
_ls = new LoadingForm();
_shown = true;
try
{
_ls.TopMost = true;
_ls.ShowDialog();
}
catch
{
}
}
}
همونطور که معلومه داخل کلاس یه ترد ایجاد میشه برای نمایش فرم پراگرس بار، این کلاس تا حدودی کار منو راه مینداخت حالا بماند که یکسری مشکلات و ارور ها هم میده حین اجرا ولی به خاطر همون ارور ها، بخش catch مربوط به try هارو خالی گذاشتم و هیچ اکسپشنی ازشون دریافت نمیکنم، اما همین امروز شروع کرد داخل دیباگر خود ویژوال ستودیو یه سری ارورهارو بهم نمایش دادن، که دوتاشونو میذارم. البته ناگفته نماند که این ارور ها فقط داخل دیباگر و در حالت دبیاگ بهم نمایش داده میشن و UI برنامه و خود فرم پراگرس بار، به مراتب داره کندتر میشه تا جایی که ارور رو بهم نمایش میده ولی توی حالت ریلیز گویا مشکلی وجود نداره و برنامه هم با کندی مواجه نمیشه.
اینم ارورهایی که میگیرم:
ارور اول:
Managed Debugging Assistant 'DisconnectedContext' : 'Transition into COM context 0x1a36328 for this RuntimeCallableWrapper failed with the following error: The callee (server [not server application]) is not available and disappeared; all connections are invalid. The call did not execute. (Exception from HRESULT: 0x80010012 (RPC_E_SERVER_DIED_DNE)). This is typically because the COM context 0x1a36328 where this RuntimeCallableWrapper was created has been disconnected or it is busy doing something else. Releasing the interfaces from the current COM context (COM context 0x1a36270). This may cause corruption or data loss. To avoid this problem, please ensure that all COM contexts/apartments/threads stay alive and are available for context transition, until the application is completely done with the RuntimeCallableWrappers that represents COM components that live inside them.'
ارور دوم:
Managed Debugging Assistant 'ContextSwitchDeadlock' : 'The CLR has been unable to transition from COM context 0x20692f8 to COM context 0x20693b0 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.'
حالا در رابطه با ارور ها میدونم داره از طولانی شدن یه عملیاتی شکایت میکنه ولی نمیدونم و نمیتونم بفهمم که چه عملیاتیه که طولانی هست، چون واقعیتش من اصلا عملیات انچنانی انجام نمیدم، فقط سلکت توسط دستورات Linq هستش، و داخل پروفایلر اس کیو ال که نگاه میکنم ببینم کوئری های اضافه ای اجرا نشن، خیر هیچ کوئری اضافه ای اجرا نمیشه و هر کوئری کمتر از 0.5 ثانیه و طولانیترینشون 1.5 ثانیه طول میکشه اجرا بشه، خب حالا که مشکلی از طرف دستورات اس کیو ال نیست، پس به این نتیجه میرسم که مشکل از خود پراگرس بار و مربوط به تردی هستش که داخلش وجود داره
حالا چندتا سوال:
1. چون در حالت ریلیز این ارور ها وجود ندارن و مشکلی هم ظاهرا از بابت کندی سرعت پیش نمیاد، آیا این مشکل رو بذارم همینجوری بمونه و نیازی نیست برطرفش کنم؟
2. آیا این روش نمایش پراگرس بار روش خوب و بهینه تری داره؟ شاید باور نکنید ولی دغدغه این پراگرس بار به اندازه کل این نرم افزاره منو پیر کرده
اگر کسی در این رابطه و این مشکل تجربه ای داره و تونسته حلش کنه لطفا راهنمایی بفرمایید