PDA

View Full Version : هنگ برنامه هنگام گرفتن سورس سایت



gachboy
چهارشنبه 24 فروردین 1401, 17:22 عصر
سلام وقت بخیر:قلب:
یک برنامه نوشتم که یک Button داره و موقعی روش کلیک میشه برنامه دو کار انجام میده :
سورس یک پیج در یوتیوب میگیره :

try {
//"google.com"


HttpWebRequest web = (HttpWebRequest)WebRequest.Create("https://www.youtube.com/channel/UC81uuy-UsdB5u-ZHiYp2XSg/videos");
web.Method = "Get";
HttpWebResponse res = (HttpWebResponse)web.GetResponse();
string source = new StreamReader(res.GetResponseStream()).ReadToEnd();
textBox1.Text = source;


}
catch
{ MessageBox.Show("خطایی در ارتباط رخ داده است", "هشدار", MessageBoxButtons.OK, MessageBoxIcon.Warning); }



و از طریق ping چک میکنه اگر نت وصل بود یک عکس در یوتیوب در picture box نمایش میده :

pictureBox1.ImageLocation = "https://i.ytimg.com/vi/T0D3vCXEak4/hqdefault.jpg";



موقعی روی Button میزنم برنامه چند ثانیه هنگ میکنه (حالا بخاطر سرعت نت یا سرعت وی *ی ان یا هر چیز دیگه...)
بنظر شما برای جلوگیری از هنگ چکار کنم؟ لطفا چون مبتدی هستم واضح توضیح بدید ممنون:قلب:

SajjadKhati
پنج شنبه 25 فروردین 1401, 10:57 صبح
سلام
احتمالا بخاطر انتظار برای جواب گرفتن (متد GetResponse) باشه (هر چند سرعت اینترنت هم حدودا تاثیر گذار هست) (بجز این ، کلا کارهای مربوط به اینترنت ، حتی پرسرعت ترین شون هم انتظار و کندی توش هست) .

این کدهای مورد نظرتون را در نخ جدیدی بسازید و توش بنویسید ، احتمالا درست بشه .

gachboy
جمعه 26 فروردین 1401, 09:22 صبح
در کل تا الان با نخ کار نکردم...میشه فقط برای گرفتن سورس یک نخ ساخت؟
چون الان اموزش های نخ که نگاه کردم متوجه شدم که برای چند کار که بصورت موازی با هم انجام بشن از نخ استفاده میکنن،
ولی الان من فقط میخوام سورس سایت گرفته بشه...الان برای همین یک کار هم باید نخ استفاده کنم؟

SajjadKhati
جمعه 26 فروردین 1401, 12:20 عصر
در کل تا الان با نخ کار نکردم...میشه فقط برای گرفتن سورس یک نخ ساخت؟


سلامی مجدد
بستگی به ساختار اون چیز داره (معمولا بعضی از اعضای کنترل های بصری ، با نخ جدید مشکل دارن) .
به احتمال بسیار زیاد ، برای گرفتن سورس ، میشه .



چون الان اموزش های نخ که نگاه کردم متوجه شدم که برای چند کار که بصورت موازی با هم انجام بشن از نخ استفاده میکنن،


بله .
چون هر نخ هم مستقل از هم کار میکنن ، نخ ها ، منتظر هم نمیمونن و در این مورد شما که میخواین نخ اصلی تون (نخی که کنترل و ui ئه برنامه تون توش نوشته شده) ، منتظر کدهای و جواب هایی که از منبع وب دریافت میکنه ، نشه (یا در اصطلاح هنگ نکنه) ، در این موردتون هم مورد استفاده قرار میگیره .

البته دقت کنید چون ماهیت نخ ها مستقل از هم هستن ، دو کد ئه مربوط به هم را درون دو نخ مجزا ننویسید یا اگه مینویسید ، باید هماهنگی بین اون نخ ها را ایجاد کنید که مهمترین قضیه ی نخ هاست و روش ها و ابزارهای گسترده ای برای این کار هست .



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


باید نداره .
بجاش از async await هم میتونین استفاده کنین که در مواردی استفاده میشه که کدی بکار بره که انتظار در اون نخ را در پی داشته باشه (مثل کدهای مربوط به ورودی و خروجی ، مثلا گرفتن اطلاعات از شبکه یا اینترنت یا خوندن و نوشتن اطلاعات در دیتابیس یا فایل یا محاسبات سنگین در پردازنده که معمولا انتظار را در پی داره) .

در واقع async await هم همون کاری شبیه نخ میکنه اما کار کردن و هماهنگی باهاش راحت تره .

gachboy
جمعه 02 اردیبهشت 1401, 14:59 عصر
میشه لطفا با مثال روی سورس بالا توضیح بدید،چون چندتا اموزش نگاه کردم متوجه نشدم

gachboy
شنبه 03 اردیبهشت 1401, 10:55 صبح
من از کد زیر هم استفاده میکنم ولی باز هنگ میکنه :
private async void button1_Click(object sender, EventArgs e) {







try
{

string url = "https://www.youtube.com/channel/UC81uuy-UsdB5u-ZHiYp2XSg/videos";
HttpClient client = new HttpClient(); // actually only one object should be created by Application
using (HttpResponseMessage response = await client.GetAsync(url))
{
using (HttpContent content = response.Content)
{
string result = await content.ReadAsStringAsync();
textBox1.Text=result;
}
}

}

catch
{ MessageBox.Show("خطایی در ارتباط رخ داده است", "هشدار", MessageBoxButtons.OK, MessageBoxIcon.Warning); }


}

gachboy
شنبه 03 اردیبهشت 1401, 11:11 صبح
مشکل فهمیدم ،طول متغیر خیلی زیاد بود بخاطر همین در خط 19 کد بالا هنگ میکرد :

SajjadKhati
شنبه 03 اردیبهشت 1401, 18:35 عصر
میشه لطفا با مثال روی سورس بالا توضیح بدید،چون چندتا اموزش نگاه کردم متوجه نشدم

سلامی مجدد
کد زیر :



private string GetHttpData()
{
try
{
//"google.com"
// "https://www.youtube.com/channel/UC81uuy-UsdB5u-ZHiYp2XSg/videos"
// "https://www.shahrsakhtafzar.com/fa/"


HttpWebRequest web = (HttpWebRequest)WebRequest.Create("https://www.youtube.com/channel/UC81uuy-UsdB5u-ZHiYp2XSg/videos");
web.Method = "Get";
HttpWebResponse res = (HttpWebResponse)web.GetResponse();
string source = new StreamReader(res.GetResponseStream()).ReadToEnd();
return source;
}
catch
{
return null;
}
}


private async void Button_Click(object sender, RoutedEventArgs e)
{
Task<string> httpDataTask = new Task<string>(new Func<string>(this.GetHttpData));
// با اجرای این خط ، متدِ GetHttpData ، در نخ جدیدی اجرا میشه .
httpDataTask.Start();
// با اجرای await ، یعنی با اجرای این خط ، ادامه ی اجرای متد جاری ، یعنی ادامه ی اجرای رویدادِ Button_Click که توش هستیم ، معلق میشه و -
// و کنترل اجرای کدها ، به متدها یا رویدادهای دیگه ای که در صفِ نخِ جاری مون هستن میپردازه .





// همچنین await ، منتظر میمونه تا متد GetHttpData که توسط متد Task.Start یا توسط Task.Run که در خط بالا در نخ جدیدی اجرا شد ، خاتمه پیدا کنه تا -
// تا بعد از اتمامش ، اولا ، هم در صورتی که مثل این مثال ، اگه متدمون که GetHttpData هست ، مقداری را برگردوند ، نتیجه ی اون ، یعنی مقدار بازگشتی اش را که رشته هست ، برگردونه و -
// و دوما ، اینکه بعد از اتمامش ، ادامه ی کد در این متد را اجرا کنه . یعنی خط های پایین اش را اجرا کنه که در همون نخ که در اینجا نخ اصلی هست ، اجرا کنه .
string httpDataString = await httpDataTask;


if (httpDataString != null)
HttpReqTextBlock.Text = httpDataString;
else
MessageBox.Show("خطایی در ارتباط رخ داده است", "هشدار");
}


درون متدی که از کلمه ی کلیدیِ await استفاده میکنید ، باید برای اون متد ، از کلمه ی کلیدیِ async استفاده کنید .
در واقع ، کلمه ی کلیدیِ async ، یه دلیگیت یا متد لازم داره که درونش از await استفاده بشه .

خود await ، به یک شیِ Task یا Tast<T> ای که قبلا اجرا شده باشه ، نیاز داره . که این شی را کنار این کلمه ی کلیدیِِ await مینویسیم .
یعنی قبل از استفاده از کلمه ی کلیدیِ await ، این شیِ Task یا Tast<T> ، باید اجرا شده باشه . حالا با متد Task.Start یا Task.Run یا Task.WhenAll قبلا باید اجرا شده باشه یا اینکه متدی را که فراخونی میکنیم و مقدار بازگشتیِ از نوع Task یا Task<T> داره ، داخلِ خودِ متد اون شیِ Task یا Task<T< را فراخونی کرده باشن .


در مثال بالا ، در متد Button_Click ، اول شیِ httpDataTask (از نوع Task<string>) ساخته شد و چون قبل از اجرای await باید اجرا بشه ، در خط بعدش با متد Task.Start ، اجرا شد . با اجرا شدنِ شیِ Task<string> ، متد GetHttpData درون نخ جدیدی اجرا میشه (نخ از نوع Background هست) .
چون متد GetHttpData ، در نخ جدید اجرا میشه ، پس همزمان ادامه ی نخ جاری مون اجرا میشه که در اینجا همون ادامه ی کد در متدِ Button_Click در نخ جاری (اصلی) مون هست .

بنابراین خط بعدش که کلمه ی کلیدی await هست ، اجرا میشه .
با اجرا شدن کلمه ی کلیدی await ، کارهای زیر انجام میشه :

- اول اینکه اجرای متدِ جاری (در اینجا متد Button_Click) ، به حالت تعلیق درمیاد . یعنی موقتا ، کدهایی که در این متد (Button_Click) در پایینِ خطِ await هستن ، اجرا نمیشه . بنابراین کنترلِ اجرای کد ، به متدها و رویدادهای دیگه ای که در اون اون نخ (نخ اصلی در اینجا) در صف انتظار هستن ، میرسه و اونها اجرا میشن و همین باعث میشه که برنامه از هنگیِ ، خارج بشه .

دقت کنید که اشتباه نکنید که چون شیِ Task را کنار await مینویسیم ، پس await باعث میشه که متدِ مورد نظر در اون Task (در اینجا متد GetHttpData) ، متوقف بشه ها . این طور نیست . بلکه ادامه ی اجرای کد در همون متدی که await توش نوشته شده را به حالت تعلیق درمیاره .

یعنی await (تا اینجا) ، کاری شبیه به کلمه ی کلیدی yield (در متد) انجام میده .

- دوم اینکه حالا await ، تا چه زمانی ادامه ی اجرای کد در متد را به حالت تعلیق در میاره؟
قبلا که شیِ Task مون اجرا شده بود (با متد Task.Start در این مثال) . که متد GetHttpData را در نخ جدیدی اجرا کرده بود .
تا زمانی که این Task مون خاتمه پیدا کنه . یعنی بعد از اتمام اجرای متد GetHttpData ، ادامه ی await در متد Button_Click اجرا میشه .

- سوم اینکه اگه شیِ Task مون ، نتیجه ای داشته باشه ، await ، نتیجه ی اون را میتونه برگردونه . یعنی مقدار پروپرتیِ Task.Result را که در اینجا همون مقدار بازگشتیِ متدِ GetHttpData مون هست را میتونه برگردونه .


* کلمه های کلیدیِ await و yield ، از لحاظِ به حالتِ تعلیق درآوردنِ متدی که توشون از این کلمات کلیدی استفاده شده ، شبیه هم هستن (یعنی هر دوشون ، متد را معلق میکنن و ادامه ی کدهای اون متد به صورت موقت ، اجرا نمیشه) منتها در زمان اجرای ادامه ی کدهای متد ، فرق میکنن .
که await ، زمانی که اجرای شیِ Task یا Task<T> ای که براش استفاده شده ، به اتمام برسه ، ادامه ی کدهای متدش اجرا میشه اما کلمه ی کلیدیِ yield ، باید خودمون (معمولا از جایی بیرون از متدی که در اون استفاده شد) اون متدی که yield در اون استفاده شده را مجددا فراخونی کنیم تا ادامه ی کدهاش اجرا بشه .

============

البته دقت کنید که این مثال ، بر پایه ی کد قبلی تون بود . یعنی بر پایه ی شیِ HttpWebRequest که همونطور در منبع اش اومده ، این کلاس قدیمی هست و بجاش از شیِ HttpClient توصیه شده استفاده کنید که در مثال پست 6 ، خودتون این کار را کردید .
که در این نوع اشیاء (مثل شیِ HttpClient) ، خودشون متدی که با نامِ Async ختم میشن و درون شون شیِ Task یا Task<T> ئه اجرا شده هست را دارن .


اطلاعات بیشتر :

Asynchronous programming - C#‎‎‎‎‎‎‎ | Microsoft Docs (https://docs.microsoft.com/en-us/dotnet/csharp/asynC#‎‎‎‎‎‎‎:~:text=The%20async%20k eyword%20turns%20a,the%20awaited%20task%20is%20com plete.)

و

Async and Await In C#‎‎‎‎‎‎‎ (c-sharpcorner.com) (https://www.c-sharpcorner.com/article/async-and-await-in-c-sharp/)

gachboy
یک شنبه 04 اردیبهشت 1401, 13:03 عصر
خیلی ممنونم بابت توضیح کامل و عالیتون:قلب:
از شی HttpClient استفاده کردم ولی برای یوتیوب که باید از وی *ی ان استفاده کرد اگر سرعت یذره کم باشه چند ثانیه طول میکشه تا جواب بگیره
البته اینم مشکل از سرعت خوبیه که داریم:لبخند:
بازم ممنونم بابت وقتی که جواب دادن گذاشتین:قلب: