How do i activate this code with a Button? - c#

As title says. I want to activate this code with a button in FormsApp, but i really do not how to do it.
public static async Task<List<string>> GetProxiesFromSslProxies()
{
try
{
string rssContent = await new WebClient().DownloadStringTaskAsync("http://sslproxies24.blogspot.de/feeds/posts/default");
XDocument feed = XDocument.Parse(rssContent);
SyndicationFeed sf = SyndicationFeed.Load(feed.CreateReader());
List<string> allProxies = new List<string>();
foreach (SyndicationItem si in sf.Items)
{
var cont = (TextSyndicationContent) si.Content;
var matches = Regex.Matches(cont.Text, #"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]{2,6}\b");
allProxies.AddRange(from Match match in matches select match.Value);
}
return allProxies.Distinct().ToList();
}
catch (Exception)
{
}
return null;
}

You have to add a button handler to your button. Then you invoke your method in the handler. You can attach the handler in the WinForms designer - just double click the button. Or you can add it in the constructor of your form:
public Form1()
{
InitializeComponent();
this.button1.Click += new System.EventHandler(this.button1_Click);
}
And the handler:
private async void button1_Click(object sender, EventArgs e)
{
var results = await GetProxiesFromSslProxies();
}

private async void Button_Click( ... )
{
List<string> proxies = await GetProxiesFromSslProxies();
//do something with 'proxies'.
}

Related

Wait users click on popup with Rg.Plugins.Popup

I show a pop up and I have to wait user's choice to put something in an entry control, the problem is that the if statment where I decide what goes as text in entry is executing at the same time as the popup shows.
I tried by making the method await but not working, here's what I have.
Donesn't matter by now the if() statement,I was just trying
This is my popup class (I want to wait until one of the buttons is clicked):
public partial class PopupElegirRFC : PopupPage
{
string sEmisor = "";
string sReceptor = "";
public PopupElegirRFC (string emisor, string receptor)
{
InitializeComponent ();
lblREmisor.Text = "Emisor: " + emisor;
lblRReceptor.Text = "Receptor: " + receptor;
sEmisor = emisor;
sReceptor = receptor;
}
private void BtnEmisor_Clicked(object sender, EventArgs e)
{
PopupNavigation.Instance.PopAllAsync();
VGlobales.sRFSeleccionado = sEmisor;
}
private void BtnReceptor_Clicked(object sender, EventArgs e)
{
PopupNavigation.Instance.PopAllAsync();
VGlobales.sRFSeleccionado = sReceptor;
}
}
This is the code where I want to wait for users choice:
case 2:
await PopupNavigation.Instance.PushAsync(new Popups.PopupElegirRFC(list[0], list[1]));
if (VGlobales.sRFSeleccionado == list[1])
{
RFCavalidar.Text = list[1];
VGlobales.sRFSeleccionado = "";
}
else
{
RFCavalidar.Text = list[0];
VGlobales.sRFSeleccionado = "";
}
break;
The code executes, but it goes directly to the if(), not waiting the user's choice
I would like to the popup to wait until some of both buttons in it is clicked. so I can make the if() validation
It's an old question but my answer can help someone.
Add TaskCompletionSource and wait for return.
Popup class:
public partial class PopupElegirRFC : PopupPage
{
private TaskCompletionSource<string> taskCompletionSource;
public Task<string> PopupClosedTask { get { return taskCompletionSource.Task; } }
string sEmisor = "";
string sReceptor = "";
public PopupElegirRFC (string emisor, string receptor)
{
InitializeComponent();
lblREmisor.Text = "Emisor: " + emisor;
lblRReceptor.Text = "Receptor: " + receptor;
sEmisor = emisor;
sReceptor = receptor;
}
protected override void OnAppearing ()
{
base.OnAppearing();
taskCompletionSource = new TaskCompletionSource<string>();
}
private void BtnEmisor_Clicked (object sender, EventArgs e)
{
taskCompletionSource.SetResult(sEmisor);
PopupNavigation.Instance.PopAllAsync();
}
private void BtnReceptor_Clicked (object sender, EventArgs e)
{
taskCompletionSource.SetResult(sReceptor);
PopupNavigation.Instance.PopAllAsync();
}
}
Code where you want to wait:
var popupElegirRFC = new Popups.PopupElegirRFC(list[0], list[1]);
await PopupNavigation.Instance.PushAsync(popupElegirRFC);
string result = await popupElegirRFC.PopupClosedTask;
if (result == list[1])
{
RFCavalidar.Text = list[1];
}
else
{
RFCavalidar.Text = list[0];
}
This idea came from the link below:
https://github.com/rotorgames/Rg.Plugins.Popup/issues/116
as jason suggested , you can use MessagingCenter to evaluate whether which button is clicked or not.
In your Button click in popup page
private void BtnEmisor_Clicked(object sender, EventArgs e)
{
MessagingCenter.Send((App)Application.Current,"BtnEmisor_Clicked");
PopupNavigation.Instance.PopAllAsync();
VGlobales.sRFSeleccionado = sEmisor;
}
In your non- Popup page
MessagingCenter.Subscribe((App)Application.Current, "BtnEmisor_Clicked", (sender) =>
{
// Do task on that button click
});

C# List.Add System.InvalidOperationException

I am handling an event from a child form in its parent form, and when I try adding items from the list contained within the event args of the handler (ScraperForm_SiteScraped in the code below), I am receiving the exception System.InvalidOperationException in my console.
Interestingly enough, it seems to succeed on the first add, but no subsequent attempts.
public partial class ProxyTesterView : UserControl
{
private BindingList<Proxy> proxies = new BindingList<Proxy>();
private BindingList<ProxyJudge> pudges = new BindingList<ProxyJudge>();
private BindingList<ProxyTest> tests = new BindingList<ProxyTest>();
private PauseOrCancelTokenSource pcts = new PauseOrCancelTokenSource();
private ProxyScraperForm scraperForm = new ProxyScraperForm();
public ProxyTesterView()
{
InitializeComponent();
proxies.ListChanged += Proxies_ListChanged;
scraperForm.SiteScraped += ScraperForm_SiteScraped;
}
private void Proxies_ListChanged(object sender, ListChangedEventArgs e)
{
ProxiesDataGridView.RowCount = proxies.Count;
}
private void AddFromScraperToolStripMenuItem_Click(object sender, EventArgs e)
{
scraperForm.Show();
}
private void ScraperForm_SiteScraped(object sender, SiteScrapedEventArgs e)
{
foreach (var proxy in e.ScrapedProxies)
{
proxies.Add(proxy);
}
}
}
Child Form
public partial class ProxyScraperForm : Form
{
private BindingList<IProxyScraperSite> sites = new BindingList<IProxyScraperSite>();
public int ScrapeInterval { get; set; } = 60000;
public event EventHandler<SiteScrapedEventArgs> SiteScraped;
public ProxyScraperForm()
{
InitializeComponent();
sites.Add(new ProxyScraperSiteUsProxyOrg());
sites.Add(new ProxyScraperSiteFreeProxyListNet());
sites.Add(new ProxyScraperSiteFreeProxyListsNet());
sites.Add(new ProxyScraperSiteHideMyName());
sites.Add(new ProxyScraperSiteHidester());
ScraperDataGridView.DataSource = sites;
}
private void ScrapeButton_Click(object sender, EventArgs e)
{
foreach (var site in sites)
{
Task.Run(async () =>
{
while (true)
{
var driver = SeleniumUtility.CreateDefaultFirefoxDriver();
var newProxies = await site.ScrapeAsync(driver);
driver.Quit();
OnSiteScraped(newProxies);
await Task.Delay(5000);
site.Status = $"Waiting {ScrapeInterval / 1000} seconds...";
await Task.Delay(ScrapeInterval);
}
});
}
}
private void OnSiteScraped(List<Proxy> scrapedProxies)
{
if (SiteScraped != null)
{
SiteScraped(this, new SiteScrapedEventArgs(scrapedProxies));
}
}
}
From our comments, turns out that this was a threading issue. As a good practice, always use a try/catch block when there's a chance that an exception can occur in a block of code. :)
Also, if you're using Visual Studio, you can make VS break on more exceptions by pressing CTRL+ALT+E and selecting the checkboxes. You can read more about exception breaking here.

Silverlight ASync call of Service overriding class member

I'm using silverlight to access a webservice to request some data. This call is asynchronous. I (think I) have to put this data in a class member after doing some operations on it, so I can access it later.
public class CardPrinter
{
// The card to be printed
private UIElement printCard;
public void PrintStaffCard(string p_persoons)
{
Debug.WriteLine(p_persoons);
foreach (string persoon in p_persoons.Split(','))
{
int p_persoon = Convert.ToInt32(persoon.Trim());
this.GetStaffData(p_persoon);
}
}
private void GetStaffData(int p_persoon)
{
PictureServiceClient proxy = new PictureServiceClient();
proxy.GetPersonelCardInfoCompleted += this.Proxy_GetPersonelCardInfoCompleted;
proxy.GetPersonelCardInfoAsync(p_persoon);
}
private void Proxy_GetPersonelCardInfoCompleted(object sender, GetPersonelCardInfoCompletedEventArgs e)
{
if (e.Error != null)
{
Debug.WriteLine(e.Error.Message);
}
else
{
this.SendStaffCardToPrinter(e.Result);
}
}
private void SendStaffCardToPrinter(CardInfo.CardInfo card)
{
Canvas canvas = new Canvas()
//Do some stuff
this.printCard = canvas;
PrintDocument pd = new PrintDocument();
pd.PrintPage += new EventHandler<PrintPageEventArgs>(this.Pd_PrintPage);
pd.Print(card.accountNr, null, true);
}
private void Pd_PrintPage(object sender, PrintPageEventArgs e)
{
e.PageVisual = this.printCard;
}
}
The problem is in the printCard variable. Sometimes it still contains the data from a previous async call in the foreach.
If I could make sure that the call in the foreach is compeletely finished there would not be a problem, but not sure how to do this and if this is the correct way to handle this.
What is the best way to handle a situation like this?
You can make the code easier to use by using TaskCompletionSource to convert the asynchronous methods from event based to task based. Then you can get rid of the variable and usage of the methods becomes much like using a synchronous method.
I haven't tested this, but it should be close to what you need. You may also find the following article useful. And also the following post Nested Asynchronous function in Silverlight
public class CardPrinter
{
public void PrintStaffCard(string p_persoons)
{
Debug.WriteLine(p_persoons);
foreach (string persoon in p_persoons.Split(','))
{
int p_persoon = Convert.ToInt32(persoon.Trim());
var cardInfo = await this.GetStaffDataAsync(p_persoon);
await this.SendStaffCardToPrinterAsync(cardInfo);
}
}
private Task<CardInfo.CardInfo> GetStaffDataAsync(int p_persoon)
{
var tcs = new TaskCompletionSource<CardInfo.CardInfo>();
PictureServiceClient proxy = new PictureServiceClient();
proxy.GetPersonelCardInfoCompleted += (s, e) =>
{
if (e.Error != null)
{
Debug.WriteLine(e.Error.Message);
tcs.SetException(e.Error);
}
else
{
tcs.SetResult(e.Result);
}
};
proxy.GetPersonelCardInfoAsync(p_persoon);
return tcs.Task;
}
private Task SendStaffCardToPrinterAsync(CardInfo.CardInfo card)
{
Canvas canvas = new Canvas();
//Do some stuff
var tcs = new TaskCompletionSource<object>();
PrintDocument pd = new PrintDocument();
pd.PrintPage += (s, e) =>
{
e.PageVisual = canvas;
tcs.SetResult(null);
};
pd.Print(card.accountNr, null, true);
return tcs.Task;
}
}
The GetPersonalCardInfoAsync method should have an overload where you can pass a UserState argument. You can pass your printCard there when you're making the call and access it later in your Proxy_GetPersonelCardInfoCompleted.
private void GetStaffData(int p_persoon, UIElement printCard)
{
PictureServiceClient proxy = new PictureServiceClient();
proxy.GetPersonelCardInfoCompleted += this.Proxy_GetPersonelCardInfoCompleted;
proxy.GetPersonelCardInfoAsync(p_persoon, printCard);
}
private void Proxy_GetPersonelCardInfoCompleted(object sender, GetPersonelCardInfoCompletedEventArgs e)
{
UIElement printCard = (UIElement)e.UserState;
// do stuff
}

How to call WebBrowser Navigate to go through a number of urls?

To collect information on a webpage, I can use the WebBrowser.Navigated event.
First, navigate to the url:
WebBrowser wbCourseOverview = new WebBrowser();
wbCourseOverview.ScriptErrorsSuppressed = true;
wbCourseOverview.Navigate(url);
wbCourseOverview.Navigated += wbCourseOverview_Navigated;
Then process the webpage when Navigated is called:
void wbCourseOverview_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
//Find the control and invoke "Click" event...
}
The difficult part comes when I try to go through a string array of urls.
foreach (var u in courseUrls)
{
WebBrowser wbCourseOverview = new WebBrowser();
wbCourseOverview.ScriptErrorsSuppressed = true;
wbCourseOverview.Navigate(u);
wbCourseOverview.Navigated += wbCourseOverview_Navigated;
}
Here, because the page load takes time, wbCourseOverview_Navigated is never reached.
I tried to use the async await in C#5. Tasks and the Event-based Asynchronous Pattern (EAP) is found in here. Another example can be found in The Task-based Asynchronous Pattern.
The problem is WebClient has async method like DownloadDataAsync and DownloadStringAsync. But there is no NavigateAsync in WebBrowser.
Can any expert give me some advice? Thank you.
There is a post in StackOverflow (here). But, does anyone know how to implement that strut in its answer?
Update again.
Suggested in another post here in StackOverflow,
public static Task WhenDocumentCompleted(this WebBrowser browser)
{
var tcs = new TaskCompletionSource<bool>();
browser.DocumentCompleted += (s, args) => tcs.SetResult(true);
return tcs.Task;
}
So I have:
foreach (var c in courseBriefs)
{
wbCourseOverview.Navigate(c.Url);
await wbCourseOverview.WhenDocumentCompleted();
}
It looks good until my web browser visits the second url.
An attempt was made to transition a task to a final state when it had already completed.
I know I must have made a mistake inside the foreach loop. Because the DocumentCompleted event has not been raised when it loops to the second round. What is the correct way to write this await in a foreach loop?
There is a post in StackOverflow (here). But, does anyone know how to implement that strut in its answer?
Ok, so you want some code with awaiter. I've made two pieces of code.
The first one uses TPL's built-in awaiter:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ProcessUrlsAsync(new[] { "http://google.com", "http://microsoft.com", "http://yahoo.com" })
.Start();
}
private Task ProcessUrlsAsync(string[] urls)
{
return new Task(() =>
{
foreach (string url in urls)
{
TaskAwaiter<string> awaiter = ProcessUrlAsync(url);
// or the next line, in case we use method *
// TaskAwaiter<string> awaiter = ProcessUrlAsync(url).GetAwaiter();
string result = awaiter.GetResult();
MessageBox.Show(result);
}
});
}
// Awaiter inside
private TaskAwaiter<string> ProcessUrlAsync(string url)
{
TaskCompletionSource<string> taskCompletionSource = new TaskCompletionSource<string>();
var handler = new WebBrowserDocumentCompletedEventHandler((s, e) =>
{
// TODO: put custom processing of document right here
taskCompletionSource.SetResult(e.Url + ": " + webBrowser1.Document.Title);
});
webBrowser1.DocumentCompleted += handler;
taskCompletionSource.Task.ContinueWith(s => { webBrowser1.DocumentCompleted -= handler; });
webBrowser1.Navigate(url);
return taskCompletionSource.Task.GetAwaiter();
}
// (*) Task<string> instead of Awaiter
//private Task<string> ProcessUrlAsync(string url)
//{
// TaskCompletionSource<string> taskCompletionSource = new TaskCompletionSource<string>();
// var handler = new WebBrowserDocumentCompletedEventHandler((s, e) =>
// {
// taskCompletionSource.SetResult(e.Url + ": " + webBrowser1.Document.Title);
// });
// webBrowser1.DocumentCompleted += handler;
// taskCompletionSource.Task.ContinueWith(s => { webBrowser1.DocumentCompleted -= handler; });
// webBrowser1.Navigate(url);
// return taskCompletionSource.Task;
//}
And the next sample contains the sample implementation of awaiter struct Eric Lippert was talking about here.
public partial class Form1 : Form
{
public struct WebBrowserAwaiter
{
private readonly WebBrowser _webBrowser;
private readonly string _url;
private readonly TaskAwaiter<string> _innerAwaiter;
public bool IsCompleted
{
get
{
return _innerAwaiter.IsCompleted;
}
}
public WebBrowserAwaiter(WebBrowser webBrowser, string url)
{
_url = url;
_webBrowser = webBrowser;
_innerAwaiter = ProcessUrlAwaitable(_webBrowser, url);
}
public string GetResult()
{
return _innerAwaiter.GetResult();
}
public void OnCompleted(Action continuation)
{
_innerAwaiter.OnCompleted(continuation);
}
private TaskAwaiter<string> ProcessUrlAwaitable(WebBrowser webBrowser, string url)
{
TaskCompletionSource<string> taskCompletionSource = new TaskCompletionSource<string>();
var handler = new WebBrowserDocumentCompletedEventHandler((s, e) =>
{
// TODO: put custom processing of document here
taskCompletionSource.SetResult(e.Url + ": " + webBrowser.Document.Title);
});
webBrowser.DocumentCompleted += handler;
taskCompletionSource.Task.ContinueWith(s => { webBrowser.DocumentCompleted -= handler; });
webBrowser.Navigate(url);
return taskCompletionSource.Task.GetAwaiter();
}
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ProcessUrlsAsync(new[] { "http://google.com", "http://microsoft.com", "http://yahoo.com" })
.Start();
}
private Task ProcessUrlsAsync(string[] urls)
{
return new Task(() =>
{
foreach (string url in urls)
{
var awaiter = new WebBrowserAwaiter(webBrowser1, url);
string result = awaiter.GetResult();
MessageBox.Show(result);
}
});
}
}
}
Hope this helps.
Instead of using wbCourseOverview_Navigated use webBrowser1_DocumentCompleted when fist URL load completed done your job and go to next url
List<string> urls = new List<string>();
int count = 0;
public Form1()
{
InitializeComponent();
webBrowser1.DocumentCompleted+=new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
}
private void Form1_Load(object sender, EventArgs e)
{
webBrowser1.Navigate(urls[count++]);
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//Do something
webBrowser1.Navigate(urls[count++]);
}

call an eventhandler with arguments

Visual Studio 2008, C# 3.0.
I have a method below which calls an event handler. I would like to pass the two arguments received by the method to the event handler.
I would like to do something like this:
wc.DownloadDataCompleted += wc.DownloadedDataCompleted(strtitle, placeid);
Is this even possible, if yes, how would I go about doing it ?
Code Snippet:
public void downloadphoto(string struri,string strtitle,string placeid)
{
using (WebClient wc = new WebClient())
{
wc.DownloadDataCompleted += wc_DownloadDataCompleted;
wc.DownloadDataAsync(new Uri(struri));
}
}
The easiest way to do this is to use an anonymous function (an anonymous method or a lambda expression) to subscribe to the event, then make your method have just the parameters you want:
public void downloadphoto(string struri, string strtitle, string placeid)
{
using (WebClient wc = new WebClient())
{
wc.DownloadDataCompleted += (sender, args) =>
DownloadDataCompleted(strtitle, placeid, args);
wc.DownloadDataAsync(new Uri(struri));
}
}
// Please rename the method to say what it does rather than where it's used :)
private void DownloadDataCompleted(string title, string id,
DownloadDataCompletedEventArgs args)
{
// Do stuff here
}
DownloadDataAsync has an overload which takes an object:
DownloadDataAsync(uri, object)
That object can be any arbitrary thing you want that gets passed into the DownloadDataCompleted handler:
public void downloadphoto(string struri,string strtitle,string placeid)
{
using (WebClient wc = new WebClient())
{
string[] data = new string[2] { strtitle, placeid };
wc.DownloadDataCompleted += wc_DownloadDataCompleted;
wc.DownloadDataAsync(new Uri(struri), data);
}
}
void wc_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
string[] data = (string[])e.UserToken;
string strtitle = data[0];
string placeid = data[1];
}
You could create a private class and place the handler in there. E.g.
public void downloadphoto(string struri, string strtitle, string placeid)
{
using (WebClient wc = new WebClient())
{
wcHandler handler = new wcHandler() { Strtitle = strtitle, Placeid = placeid };
wc.DownloadDataCompleted += handler.wc_DownloadDataCompleted;
wc.DownloadDataAsync(new Uri(struri));
}
}
private class wcHandler
{
public string Strtitle { get; set; }
public string Placeid { get; set; }
public void wc_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
// Do Stuff
}
}
Although, given the elegance of Jon's answer would probably use that!
Jon Skeet already answered this, showing how to use a lamda expression, but I was still unclear about it. I still needed some more examples, and eventually found this simple case using a button: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/74d03fe0-0fa5-438d-80e0-cf54fa15af0e
void A()
{
Popup parameter = new Popup();
buttonClose.Click += (sender, e) => { buttonClose_Click(sender, e, parameter); };
}
static void buttonClose_Click(object sender, EventArgs e, Popup parameter)
{
MakeSomethingWithPopupParameter(parameter);
}
In my case, I was using a context menu for a TreeView control, which ended up looking like this:
private void TreeViewCreateContextMenu(TreeNode node)
{
ContextMenuStrip contextMenu = new ContextMenuStrip();
// create the menu items
ToolStripMenuItem newMenuItem = new ToolStripMenuItem();
newMenuItem.Text = "New...";
// add the menu items to the menu
contextMenu.Items.AddRange(new ToolStripMenuItem[] { newMenuItem });
// add its event handler using a lambda expression, passing
// the additional parameter "myData"
string myData = "This is the extra parameter.";
newMenuItem.Click += (sender, e) => { newMenuItem_Click(sender, e, myData); };
// finally, set the node's context menu
node.ContextMenuStrip = contextMenu;
}
// the custom event handler, with "extraData":
private void newMenuItem_Click(object sender, EventArgs e, string extraData)
{
// do something with "extraData"
}

Categories