PDA

View Full Version : سوال: چگونه میشود یک تابع در یک نقطه متوقف کرد تا زمان که یک رویداد انجام بشه



bade saba
سه شنبه 06 مهر 1389, 15:57 عصر
سلام
دوستان من قطعه کد زیر رو نوشتم اما رشته str همیشه خالی هست و کد صفحه در خواست شده درونش ریخته نمی شه



Uri myWebUrl = new Uri("http://www.yahoo.com/");
webBrowser1.Url = myWebUrl;
string str = "";
Stream strmresponse = webBrowser1.DocumentStream;
using (StreamReader reader = new StreamReader(strmresponse, Encoding.UTF8))
{
str = reader.ReadToEnd();
}



میدونم ایراد به این دلیل هست که برنامه وقتی دستور

webBrowser1.Url = myWebUrl;
انجام میده و انتساب میکنه دیگه منتظر لود شدن پیج نمی شه و بقیه خطوط رو اجرا میکنه
سوال من اینه که چه جوری میشه برنامرو در اون خط نگه داشت تا اون event که من میخوام انجام بشه بدش بقیه برنامه ادامه پیدا کنه

چند تا مسئله رو هم بگم
اول اینکه میدونم که اگر خطوط بعدی رو در تابع


private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)


بنویسم بعد از اون رویداد انجام میشه اما مسئله اینه که بخش های مشابه زیادی در این پروژه وجود داره و اگه بخوام همرو تو این event بنویسم مشکلات زیادی مثل تو حلقه بینهایت افتاد و پیچیده شدن برای برنامه نویسی که ادامه کار غیر ممکن میکنه به وجود میاد

دوم هم این که تابع


Thread.Sleep(X);

هم به خاطر مشکلات زیادی مثل این که زمان دقیق اتمام event ورد نظر معلوم نیست کمکی نمیکنه

k1csharpdeveloper
سه شنبه 06 مهر 1389, 16:13 عصر
بنظرم توی load رویدادت بنویس تا فقط مواقع لازم اجرا بشه.

bade saba
سه شنبه 06 مهر 1389, 16:20 عصر
بنظرم توی load رویدادت بنویس تا فقط مواقع لازم اجرا بشه.


همون جوری که گفتم نمیشه در توابع مربوط به webBrowser بنویسم چون تعداد پیج های لود شده توسط webBrowser زیاده و مشکلاتی که گفتم پیش میاد

mehdi.mousavi
چهارشنبه 07 مهر 1389, 00:09 صبح
سلام.
می تونید به این شکل عمل کنید:


private void NavigateToUrl(string url)
{
this.webBrowser1.Navigate(url);
while (this.webBrowser1.ReadyState != WebBrowserReadyState.Complete)
{
Thread.Sleep(1000);
Application.DoEvents();
}
}


هر جا نیاز بود، NavigateToUrl رو Call کنید. این متود تا وقتی Page مورد نظر بطور کامل Load نشده باشه، اجراش ادامه پیدا خواهد کرد.

اما، به خط Application.DoEvents دقت کنید. این دستور باعث میشه تا کلیه پیامهای موجود در صف پیامها در لحظه فراخوانی، پردازش بشن. این به این معنی هستش که اگر Timer ای دارید، تایمر شما کار خواهد کرد، اگر برنامه رو ببندید (هنگامیکه اجرا در این Loop متوقف شده)، برنامه بسته خواهد شد و بطور کلی، اگر پیامی برای Window ی شما ارسال بشه، اون پیام پردازش میشه! این مساله بسیار میتونه خطرناک باشه و قبلا در موردش توضیح داده ام. اگر به انجام این کار اصرار دارید، بهتره با پیاده سازی IMessageFilter روی یک کلاس خاص، و اضافه کردن MessageFilter به Application قبل از فراخوانی DoEvents، پیامهایی رو پردازش کنید که مربوط به Web Browser میشه و لاغیر. اینطوری خطری برنامه شما رو تهدید نخواهد کرد... در غیر اینصورت، اگر کد بالا رو Copy & Paste کنید، ممکنه با شرایط از غیر منتظره ای در برنامه روبرو بشید و این مساله اجتناب ناپذیره.

اما سوال اصلی اینه که چه اصراری به این کار دارید؟ هدفتون فقط Load کردن یک یا چندین URL خاص هستش؟ در واثع اگر به Content صفحات نیاز دارید، روشهای بهتری وجود داره و نیازی به استفاده از Web Browser نیست. اما اگر واقعا میخواهید محتوای URL هایی رو به کاربر نشون بدید و اصرار دارید این کار رو Synchronous انجام بدید، میتونید با توجه به توضیحاتی که دادم از روش فوق استفاده کنید.

موفق باشید.

bade saba
چهارشنبه 07 مهر 1389, 02:27 صبح
اول اینکه ممنونم از این که جواب دادید

در مورد اینکه چرا میخوام این کار رو انجام بدم.
من پروژه ای میخوام بنویسم که روندی مشابه روند زیر رو باید طی کنه

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

مثلا برای ایمیل

1) ببینه اتصال به اینترنت داریم یا نه
2) وارد سایت یاهو بشه
3) رو لینک sign in کلیک کنه
4) یوزر و پسورد رو وارد کنه و لینک login رو کلیک کنه
5) تو ایمیل رو لینک inbox کلیک کنه و اطلاعات 5 تا ایمیل اول رو بازیابی کنه و به کاربر نشون بده


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




HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("http://www.sampleSite.com/login.php");

byte[] content = Encoding.UTF8.GetBytes("username and pass str");
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.KeepAlive = true;

webRequest.ContentLength = content.Length;
Stream newStream = webRequest.GetRequestStream();
newStream.Write(content, 0, content.Length);
newStream.Close();
webRequest.CookieContainer = newCookieContainer();
HttpWebResponse webResponse;
webResponse = (HttpWebResponse)webRequest.GetResponse();

string html;
using (Stream strmresponse = webResponse.GetResponseStream())
{
using (StreamReader reader = newStreamReader(strmresponse, Encoding.UTF8))
{
html = reader.ReadToEnd();
}
}



با این کد میتونستم لاگین کنم اما از پیج اول جلوتر نمی تونستم برم و دائم از حساب بیرون انداخته میشدم ، این مشکل احتمالا به خاطر عدم مدیریت cookies بود اما راه حلی براش پیدا نکردم به همین خاطر رفتم سراغ webBrowser و با استفاده ازکد زیر تونستم لاگین کنم



if (webBrowser1.Document != null)
{
HtmlElementCollection elements = webBrowser1.Document.Forms["Login"].All;
foreach (HtmlElement element in elements)
switch (element.GetAttribute("name"))
{
case"username":
element.SetAttribute("value", "myUsername");
break;
case"password":
element.SetAttribute("value", "myPass");
break;
}
foreach (HtmlElement element in elements)
if (element.GetAttribute("name") == "button")
element.InvokeMember("click");
}



و تا زمانی که ایونت set کردن url هارو داخل یه دکمه مینوشتم و خودم زمان set شدنش رو مشخص میکردم در زمینه بیرون افتادن از حساب مشکلی نداشتم اما وقتی کدهارو پشت هم نوشتم به مشکلی که تو تاپیک مطرح کردم بر خوردم



حالا شما برای انجام این پروژه استفاده از کدوم روش رو پیشنهاد میکنید؟؟؟
اگه روش اول میشه توضیح بدید اون مشکل رو چه جوری باید حل کنم؟؟؟(بیرون افتادن از حساب) و اگه روش سومی هست لطفا در موردش یه مقدار توضیح بدید