backgroundWorker with foreach - c#

The program does not follow the logic, I need it to do the request according to the order of the items of the listbox
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
foreach (var listBoxItem in listBox1.Items)
{
for (int j = 0; j < listBox1.Items.Count; j++)
{
string lista = listBox1.Items[j].ToString();
string[] split = lista.Split(';');
num.Text = split[0];
v1.Text = split[1];
v2.Text = split[2];
c.Text = split[3];
WebClient client = new WebClient();
client.Proxy = null;
client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(this.asyncWebRequest_DownloadDataCompleted);
client.DownloadDataAsync(new Uri("http://127.0.0.1/sv/" + num.Text));
j++;
}
}
}
private void asyncWebRequest_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
string #string = Encoding.Default.GetString(e.Result);
if (#string.Contains("uva"))
{
this.listBox2.Items.Add(numero.Text);
}
}
The program should make the download request of the string with EACH item in the listbox
example:
DownloadString http://127.0.0.1/sv/ + num.text and check if it contains a particular string
I need it to do the following
DownloadString http://127.0.0.1/sv/ + num.text
if
DownloadedString contains uva
then
listbox2.items.add(num.text)
else
next item from listbox1

There's so much wrong with this code, it's no wonder it's going wrong.
You're using Background Workers, don't, you should be using Tasks and async/await
You're looping over every item in the listbox twice, why?
You're spinning up multiple web clients with event subscriptions that are never disposed - probably gonna be leaking some memory here.
Here's how I'd do it:
public async void ButtonThatStartsEverything_Click(object sender, EventArgs e)
{
await DoTheDownloadStuff();
}
public async Task DoTheDownloadStuff()
{
var client = new WebClient();
foreach(var item in ListBox1.Items)
{
var expanded = item.Split(';');
var num = expanded[0];
var result = await client.DownloadDataAsyncTask(new Uri("http://127.0.0.1/sv/" + num));
if (result.Contains("uva"))
{
listBox2.Items.Add(num);
}
}
}
Please be aware that the code was written outside of Visual Studio, it may not be 100% accurate, and may not represent best practice overall e.g. You may want to download the data in parallel, which would require a change.
This code has all the basic stuff you need though.

Related

C# Invoking ListView not working (Background Thread)

Im working with WinForms.
I want to populate ListView from background thread but when im Invoking listview my program stops and shows an error. The error is "Cannot acces a disposed object. Object name is: ListView." And when i put this method
lvValidate.Invoke((Action)delegate
{
lvValidate.Items.Add(listitem);
});
in a try-catch block my program starts lagging. I dont know where is the problem,but my Invoke method is:
static class Intercept
{
internal static void Invoke(this Control control, Action action)
{
control.Invoke(action);
}
}
The error only showing when i close the form and open another form (in the same program). In the Form which contains the ListView the data is unreadable and it seems loads a thousands times.
Here's what my DoWork,ProgressChanged,RunWorkerCompleted event does.
private void bgwLoad_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
string commandText = "SELECT * FROM works";
MySqlCommand command = new MySqlCommand(commandText, connection);
MySqlDataAdapter da = new MySqlDataAdapter(command);
connection.Close();
connection.Open();
reader = command.ExecuteReader();
connection.Close();
DataTable dt = new DataTable();
da.Fill(dt);
for (int i = 0; i < dt.Rows.Count; i++)
{
DataRow dr = dt.Rows[i];
ListViewItem listitem = new ListViewItem(dr["ID"].ToString(), dr["Date"].ToString());
listitem.SubItems.Add(dr["Date"].ToString());
listitem.SubItems.Add(dr["Name"].ToString());
listitem.SubItems.Add(dr["WorkNumber"].ToString());
listitem.SubItems.Add(dr["WorkCode"].ToString());
listitem.SubItems.Add(dr["CoreThread"].ToString());
listitem.SubItems.Add(dr["Tech"].ToString());
listitem.SubItems.Add(dr["From"].ToString());
listitem.SubItems.Add(dr["To"].ToString());
listitem.SubItems.Add(dr["Validate"].ToString());
listitem.SubItems.Add(dr["Validate2"].ToString());
lvValidate.Items.Add(listitem);
}
}
private void bgwLoad_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
}
private void bgwLoad_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
picLoading.Visible = false;
}
Try the following:
Dispatcher.CurrentDispatcher.Invoke(() => {
lvValidate.Items.Add(listitem);
});
EDIT:
Or Try this:
public static void AddItem(ListItem listitem)
{
if (lvValidate.InvokeRequired)
{
AddItemDelegate d = new AddItemDelegate (AddItem);
lvValidate.Invoke(d, new object[] { listitem });
}
else
{
lvValidate.Invoke(new Action(() =>
{
lvValidate.Items.Add(listitem);
}));
}
}
delegate void AddItemDelegate(ListItem listitem);
Then call:
AddItem(listitem);
According to your comments, you are trying to retrieve Data from a DB using a DataAdapter, then handing out the Data piecemeal. This will not work for several reasons:
DataAdapter
The DataAdapter Classes all have in common that they only work, while the DBConnection is actively open. That is why you get "Cannot acces a disposed object". Because by the time you try to use it, it the connection is already Disposed. And disposing is not a thing you should ever delay. Or split up at all. Keep the using (that you hopefully got) right where it is, inside the DoWork().
For that reason you always have to copy the data of the DataAdapter into a non-Adapter collection. Really any old list would do. This will temporarily double the Memory load and might procude some stuff for the GC to clean up, but is really they only adviseable way.
Bulk Writes only in Completed
While you can theoretically hand out Partial Reads/process results via Progress Reporting, this is not adviseable to try. Writing a GUI has a massive overhead. The first and only time I did that, I ended up locking up my GUI thread with Write and Draw Operations. It looked like I had never done Multitasking. Updating a Progress bar is just about low cost enough to never really cause issues.
The default pattern is to only over write relevant amount of data after you got it all.
If you run into a exception or cancel, the pattern is to asume that all data is faulty and not have it on the UI.
I like to call the BackgroundWorker "Multitasking/-Threading Training Wheels". They teach you all those things. The firt part, by making the handing out akward. The second part, by actually throwing a Exception if you try to use the Result in invalid cases.
You propably retreive too much
Perhaps the most common mistake with DB's, is trying to retrieve a lot of data to then do processing or filtering in the Client. A common mistake, so avoid it.
There is a limit to how much data a User can process whatever you would define as 1 page. Never more then 100 Data Fields at once is my advice. If you got do Filtering, Pagination or the sort, always do it in the Query. Moving this stuff to the client moves a lot of unesessary data over the Network to then be slower at processing/Filtering then the DB would ever have been.
Example code
This actually is my first BGW Project. I updated it a bit over the years, but the bulk of it is still valid:
#region Primenumbers
private void btnPrimStart_Click(object sender, EventArgs e)
{
if (!bgwPrim.IsBusy)
{
//Prepare ProgressBar and Textbox
int temp = (int)nudPrim.Value;
pgbPrim.Maximum = temp;
tbPrim.Text = "";
//Start processing
bgwPrim.RunWorkerAsync(temp);
}
}
private void btnPrimCancel_Click(object sender, EventArgs e)
{
if (bgwPrim.IsBusy)
{
bgwPrim.CancelAsync();
}
}
private void bgwPrim_DoWork(object sender, DoWorkEventArgs e)
{
int highestToCheck = (int)e.Argument;
//Get a reference to the BackgroundWorker running this code
//for Progress Updates and Cancelation checking
BackgroundWorker thisWorker = (BackgroundWorker)sender;
//Create the list that stores the results and is returned by DoWork
List<int> Primes = new List<int>();
//Check all uneven numbers between 1 and whatever the user choose as upper limit
for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2)
{
//Report progress
thisWorker.ReportProgress(PrimeCandidate);
bool isNoPrime = false;
//Check if the Cancelation was requested during the last loop
if (thisWorker.CancellationPending)
{
//Tell the Backgroundworker you are canceling and exit the for-loop
e.Cancel = true;
break;
}
//Determin if this is a Prime Number
for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2)
{
if (PrimeCandidate % j == 0)
isNoPrime = true;
}
if (!isNoPrime)
Primes.Add(PrimeCandidate);
}
//Tell the progress bar you are finished
thisWorker.ReportProgress(highestToCheck);
//Save Return Value
e.Result = Primes.ToArray();
}
private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pgbPrim.Value = e.ProgressPercentage;
}
private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
pgbPrim.Value = pgbPrim.Maximum;
this.Refresh();
if (!e.Cancelled && e.Error == null)
{
//Show the Result
int[] Primes = (int[])e.Result;
StringBuilder sbOutput = new StringBuilder();
foreach (int Prim in Primes)
{
sbOutput.Append(Prim.ToString() + Environment.NewLine);
}
tbPrim.Text = sbOutput.ToString();
}
else
{
tbPrim.Text = "Operation canceled by user or Exception";
}
}
#endregion

how to use await and async with richtextbox?

i tried to make a app to check ebay current watchers. i use following code find ebay watcher count.. it woks fine. then i use await asyncro code to fix UI blocking..
but it is getting invalidoperationexception was unhandled exception.
private async void button1_Click(object sender, EventArgs e)
{
Task<int> task = new Task<int>(counting);
task.Start();
label1.Text = "Please wait";
await task;
}
private int counting()
{
string[] idlist = richTextBox1.Text.Split('\n'); // <= getting exception
// foreach (string id in idlist)
for (int i = 0; i < Convert.ToInt32(idlist.Length); i++)
{
string url = "http://m.ebay.com/itm/" + idlist[i];
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream());
// richTextBox2.Text += sr.ReadToEnd();
string a = sr.ReadToEnd();
sr.Close();
string number = String.Empty;
string pattern = #"(?<=""defaultWatchCount""\s*:\s*)\d+";
string input = a;
foreach (Match m in Regex.Matches(input, pattern))
{
number = m.Value;
}
richTextBox2.Text += number + Environment.NewLine;
}
return 0;
}
I don't have much knowledge about await and async... could anyone plz fix this error?
Trying to access UI controls from a thread different to the one that created it will cause cross thread access violations. So if the goal is to make the web calls on a background thread then you need to separate the background tasks from the UI
The following is a refactor of the original code that takes a collection of ids and using HttpClient to make asynchronous web calls. All the web calls will be done in parallel on separate threads.
static Lazy<HttpClient> client = new Lazy<HttpClient>(() => {
string baseUrl = "http://m.ebay.com/itm/";
var client = new HttpClient() {
BaseAddress = new Uri(baseUrl)
};
return client;
});
private Task<string[]> GetWatchCountsAsync(string[] idlist) {
string pattern = #"(?<=""defaultWatchCount""\s*:\s*)\d+";
var tasks = idlist.Select(async id => {
var input = await client.Value.GetStringAsync(id.Trim());
string number = String.Empty;
foreach (Match m in Regex.Matches(input, pattern)) {
number += m.Value;
}
return number;
});
return Task.WhenAll(tasks);
}
So now in the button click handler you start in the UI thread, offload the requests to other threads and wait for them to complete while not locking the UI thread. Once complete you extract the returned values and pass them on as needed
private async void button1_Click(object sender, EventArgs e) {
label1.Text = "Please wait..."; //UI Thread
var idlist = richTextBox1.Text.Split('\n'); //UI Thread
var numbers = await GetWatchCountsAsync(idlist); //background thread(s) (non-blocking)
richTextBox2.Text += string.Join(Environment.NewLine, numbers); // Back on UI thread
label1.Text = "Done"; //UI Thread
}

Background worker stealing main thread

So I can't say for sure this is the issue but I'm just about positive it is. I have a recordset of IVR calls to make. I put the data for each one in a concurrent queue and start 5 background workers to start working from the queue. However, after making 2 calls, the calls stop coming until one person hangs up, then it moves on to call number 3,4,5 etc. Are the any issues with this code?
It seems like the background workers are blocking eachother from calling the same method...? Is that possible?
private ConcurrentQueue<DataTable> _ivrCallsQueue = new ConcurrentQueue<DataTable>();
private List<BackgroundWorker> _ivrCallers = new List<BackgroundWorker>();
public overrid void Process()
{
foreach(DataRow row in _tblRecordsToProcess.Rows)
{
_workingActionItem = actionItemDAL.GetActionItemFromId(Convert.ToInt32(row["FNActionItemId"].ToString()));
var workingActionItemsTable = actionItemDAL.GetActionItemParamValues(Convert.ToInt32(row["FNActionItemId"].ToString()));
ivrCallsQueue.Enqueue(workingActionItemsTable);
}
StartCalls();
while (_ivrCallers.Count != 0)
{
testurls = testurls;
}
}
private void StartCalls()
{
int maxLines = 5;
if (_ivrCallsQueue.Count < maxLines)
{
maxLines = _ivrCallsQueue.Count;
}
for (int i = 0; i < maxLines; i++)
{
DataTable workingCall = new DataTable();
_ivrCallsQueue.TryDequeue(out workingCall);
BackgroundWorker ivrCaller = new BackgroundWorker();
_ivrCallers.Add(ivrCaller);
ivrCaller.DoWork += delegate(object sender, DoWorkEventArgs e)
{
RequestIVR(workingCall, Convert.ToInt32(workingCall.Rows[2][0].ToString()));
_ivrCallers.Remove(ivrCaller);
};
ivrCaller.RunWorkerCompleted += (bw_AnalyzeResults);
ivrCaller.RunWorkerAsync();
}
}
private void bw_AnalyzeResults(object sender, RunWorkerCompletedEventArgs e)
{
DataTable workingCall = new DataTable();
if (_ivrCallsQueue.Count != 0)
{
_ivrCallsQueue.TryDequeue(out workingCall);
BackgroundWorker ivrCaller = new BackgroundWorker();
ivrCaller.DoWork += delegate(object completeSender, DoWorkEventArgs completeArgs)
{
RequestIVR(workingCall, Convert.ToInt32(workingCall.Rows[2][0].ToString()));
_ivrCallers.Remove(ivrCaller);
};
ivrCaller.RunWorkerCompleted += (bw_AnalyzeResults);
ivrCaller.RunWorkerAsync();
}
else
{
}
}
private void RequestIVR(DataTable workingTable,int fnActionItemID)
{
var urlRequest = "http://uccx_http_trigger:9080/test?strTestMode=1&strTaskID=" + fnActionItemID;
var webClient = new WebClient { UseDefaultCredentials = true, Proxy = WebRequest.DefaultWebProxy };
DecodeResponseType(GetValueFromElement("Response Code was ", webClient.DownloadString(urlRequest)));
}
This will spawn at most five threads that each attempt to pull the next item from the queue and process it. If the queue is empty the attempt will fail and the thread will simply exit:
private List<System.Threading.Thread> Threads = new List<System.Threading.Thread>();
private ConcurrentQueue<DataTable> _ivrCallsQueue = new ConcurrentQueue<DataTable>();
private void StartCalls()
{
int maxLines = Math.Min(5 , _ivrCallsQueue.Count);
for (int i = 0; i < maxLines; i++ )
{
System.Threading.Thread T = new System.Threading.Thread(delegate()
{
DataTable workingCall;
while (_ivrCallsQueue.TryDequeue(out workingCall))
{
RequestIVR(workingCall, Convert.ToInt32(workingCall.Rows[2][0].ToString()));
}
});
Threads.Add(T);
T.Start();
}
}
The threads will keep running until all the items have been processed.
It looks like bw_AnalyzeResults does pretty much the same thing that StartCalls() does. In other words, when the background worker has finished its work, you immediately enqueue the same work to happen again, recursively forever?
By the looks of it, you want bw_AnalyzeResults to analyze the results returned by calling your web service. That is not what is happening at the moment.
The code below taken from the bw_AnalyzeResults event handler is scheduling a background job and making itself handle the RunWorkerCompleted event. So, presumably the software keeps going around and around executing bw_AnalyzeResults forever until you kill the process?
private void bw_AnalyzeResults(object sender, RunWorkerCompletedEventArgs e)
{
ivrCaller.DoWork += delegate(object completeSender, DoWorkEventArgs completeArgs)
{
RequestIVR(workingCall, Convert.ToInt32(workingCall.Rows[2][0].ToString()));
_ivrCallers.Remove(ivrCaller);
};
ivrCaller.RunWorkerCompleted += (bw_AnalyzeResults);
}

issue with web browser control not waiting till events performed?

Im trying to get into some webpages and get some information, using web browser so that it remembers my login details. things worked till here but for multiple urls web browser document load is not working properly as i want.
My intention was go to url->wait till it loads--> get required data into text--> new url and same process.
i used for loop to change url but when i run all the url's passed one by one not waiting till document loads and writes to text. please help me.
private void button1_Click_1(object sender, EventArgs e)
{
String text = File.ReadAllText("links.txt");
var result = Regex.Split(text, "\r\n|\r|\n");
foreach (string s in result)
{
listBox1.Items.Add(s);
}
for (int i = 0; i < listBox1.Items.Count; i++)
{
this.Text = Convert.ToString(i + 1) + "/" + Convert.ToString(listBox1.Items.Count);
textBox1.Text += listBox1.Items[i];
String url = textBox1.Text;
webBrowser2.ScriptErrorsSuppressed = true;
webBrowser2.DocumentCompleted += webBrowser2_DocumentCompleted;
webBrowser2.Navigate(url);
}
}
void webBrowser2_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
string sourceCode = webBrowser2.DocumentText;
try
{
/*someregax expressions to filter text */
StreamWriter sw = new StreamWriter("inks_info.txt", true);
sw.Write("url" + "~" + sourceCode + "\n");
sw.Close();
textBox1.Text = "";
}
catch
{
StreamWriter sw = new StreamWriter("inks_fail.txt", true);
sw.Write(textBox1.Text + "\n");
sw.Close();
textBox1.Text = "";
}
}
You have an event handler on the document load for each item, but you're not waiting for it to fire after the first navigation before you initiate the second navigation. Your for loop needs to be "more asynchronous". For example, placing items in a queue and requesting one at a time:
Queue<string> _items;
private void button1_Click_1(object sender, EventArgs e)
{
String text = File.ReadAllText("links.txt");
_items = new Queue<string>(Regex.Split(text, "\r\n|\r|\n"));
webBrowser2.ScriptErrorsSuppressed = true;
webBrowser2.DocumentCompleted += webBrowser2_DocumentCompleted;
RequestItem();
}
private void RequestItem()
{
if (_items.Any())
{
var url = _items.Dequeue(); // preprocess as required
webBrowser2.Navigate(url);
}
}
void webBrowser2_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// Handle result
RequestItem(); // Then request next item
}
Your code also looks like it's using UI elements (like a list box) as intermediate variables just for a logical purpose rather than display. You should separate out the logic (using regular variables, data structures such as lists and requesting data) from the display (showing the results in list boxes, updating text boxes, etc). It's not clear that you want to be using a WebBrowser even - it looks like you're just downloading text and should use WebClient or HttpClient. The code can then also be much cleaner using async/await:
foreach (var url in urls)
{
string text = await new WebClient().DownloadStringAsync(url);
// Handle text
}
Very Simple answer. The WebBorwser control sucks for this stuff but here is what you are looking for:
WHILE(webBrowser.ReadyState != WebBrowserReadyState.Ready)
{
Application.DoEvents()
}
Thats it.. It will not freeze your app or get you lost in code, it just waits till its don't navigating. You be most welcome.

Multiple asynchronous method calls in a loop Window Phone 7

I have a collection of picture Objects for which I need to download thumbs and pictures files located on dataservise, how can I managed this?
In this method I have loop to call three methods; one to add objects to data base, second to download and save picture thumb and third to download and save picture file the other two is ClientOpenReadCompleted methods.
public bool AddAllPhoto()
{
var amount = App.ViewModel.NewPictures.Count;
for (int i = 0; i < amount; i++)
{
//to add picture to DB
SavePicture(App.ViewModel.NewPictures[i]);
DownloadPicture(NewPictures[i].ID.ToString());
DownloadPictureThumb(NewPictures[i].ID.ToString()));
}
return true;
}
Second;
public void DownloadPictureThumb(string path)
{
string outputString = String.Format("http://" + App.ServerAdress + "/ /Pictures/Thumbs/{0}.jpg", path);
var client = new WebClient();
client.OpenReadCompleted += ClientOpenReadCompleted1;
client.OpenReadAsync(new Uri(outputString));
}
private static void ClientOpenReadCompleted1(object sender, OpenReadCompletedEventArgs e)
{
var resInfo = new StreamResourceInfo(e.Result, null);
var reader = new StreamReader(resInfo.Stream);
byte[] contents;
using (var bReader = new BinaryReader(reader.BaseStream))
{
contents = bReader.ReadBytes((int)reader.BaseStream.Length);
}
var file = IsolatedStorageFile.GetUserStoreForApplication();
var thumbFilePath = String.Format(PicturesThumbsColectionKey + "{0}", PictureDataStoreLocal.ID);
var stream = thumbFile.CreateFile(thumbFilePath);
stream.Write(contents, 0, contents.Length);
stream.Close();
}
And third one
public void DownloadPicture(string path)
{
string outputString = String.Format("http://" + App.ServerAdress + "/Pictures/{0}.jpg", path);
var client = new WebClient();
client.OpenReadCompleted += ClientOpenReadCompleted1;
client.OpenReadAsync(new Uri(outputString));
}
private static void ClientOpenReadCompleted1(object sender, OpenReadCompletedEventArgs e)
{
var resInfo = new StreamResourceInfo(e.Result, null);
var reader = new StreamReader(resInfo.Stream);
byte[] contents;
using (var bReader = new BinaryReader(reader.BaseStream))
{
contents = bReader.ReadBytes((int)reader.BaseStream.Length);
}
var file = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream stream = file.CreateFile(PictureDataStoreLocal.ID.ToString());
stream.Write(contents, 0, contents.Length);
stream.Close();
}
I assume you want to process the pictures synchronously. If so I would use a wait handle. The easiest way to do this would be to declare a private AutoResetEvent field. The AutoResetEvent is good here because it just lets one thread through and then blocks again automatically.
If you do this you will need to make sure of two things:
1. You do ALL work on a different thread so that when you call WaitOne() you aren't blocking the thread that is supposed to be doing the work.
2. You always reset the wait handle regardless of the outcome of the server calls.
To take care of 1. you just need to update your loop:
m_waitHandle.Reset(); // Make sure the wait handle blocks when WaitOne() is called
for (int i = 0; i < amount; i++)
{
// Process on a background thread
ThreadPool.QueueUserWorkItem((obj) =>
{
// Get the current index. This is an anonymous method so if
// we use 'i' directly we will not necessarily be using the
// correct index. In our case the wait handle avoids this
// problem as the pictures are downloaded one after the other
// but it's still good practise to NEVER use a loop variable in
// an anonymous method.
int index = (int)obj;
//to add picture to DB
SavePicture(App.ViewModel.NewPictures[index]);
DownloadPicture(NewPictures[index].ID.ToString());
DownloadPictureThumb(NewPictures[index].ID.ToString()));
}, i);
m_waitHandle.WaitOne(); // Wait for processing to finish
}
For 2. you need to make sure that m_waitHandle.Set() is ALWAYS called when processing is finished.
What I do is send extra parameters to the OpenReadCompleted event using a delegate like so,
someimage.LoadingCompleted += delegate(object sender, EventArgs imge) { someimage_LoadingCompleted(sender, imge, _item, "someimage"); };
and then in someimage_LoadingCompleted I have code within a switch statement.
Here is my solution, not that elegant but working one; If you have any suggestion to improve , please post and I will edit my post.
EventWaitHandle m_WaitHandle;
public bool AddAllPhoto()
{
var amount = App.ViewModel.NewPictures.Count;
if (m_WaitHandle!=null)
m_WaitHandle.Reset();
for (int i = 0; i < amount; i++)
{
{
SavePicture(App.ViewModel.NewPictures[i]);
ThreadPool.QueueUserWorkItem((obj) =>
{
var index = (int)obj;
DownloadPictureThumb(App.ViewModel.NewPictures[index].ID.ToString());
DownloadPicture(App.ViewModel.NewPictures[index].ID.ToString());
},i);
if (m_WaitHandle != null) m_WaitHandle.WaitOne();
}
return true;
}
public void DownloadPictureThumb(string path)
{
string outputString = String.Format("http://" + App.ServerAdress + "/Pictures/Thumbs/{0}.jpg", path);
var client = new WebClient();
client.OpenReadCompleted += ClientOpenReadCompleted2;
client.OpenReadAsync(new Uri(outputString),path);
}
private static void ClientOpenReadCompleted2(object sender, OpenReadCompletedEventArgs e)
{
var resInfo = new StreamResourceInfo(e.Result, null);
var reader = new StreamReader(resInfo.Stream);
byte[] contents;
using (var bReader = new BinaryReader(reader.BaseStream))
{
contents = bReader.ReadBytes((int)reader.BaseStream.Length);
}
var file = IsolatedStorageFile.GetUserStoreForApplication();
var thumbFilePath = String.Format(PicturesThumbsColectionKey + "{0}", e.UserState as string);
var stream = file.CreateFile(thumbFilePath);
stream.Write(contents, 0, contents.Length);
stream.Close();
}
public void DownloadPicture(string path)
{
string outputString = String.Format("http://" + App.ServerAdress + "/Pictures/{0}.jpg", path);
var client = new WebClient();
client.OpenReadCompleted += ClientOpenReadCompleted1;
client.OpenReadAsync(new Uri(outputString), path);
}
private static void ClientOpenReadCompleted1(object sender, OpenReadCompletedEventArgs e)
{
var resInfo = new StreamResourceInfo(e.Result, null);
var reader = new StreamReader(resInfo.Stream);
byte[] contents;
using (var bReader = new BinaryReader(reader.BaseStream))
{
contents = bReader.ReadBytes((int)reader.BaseStream.Length);
}
var file = IsolatedStorageFile.GetUserStoreForApplication();
var stream = file.CreateFile(e.UserState as string);
stream.Write(contents, 0, contents.Length);
stream.Close();
}
[Here][1] you will find explanation to how to get the url from WebClient in OpenReadCompleted?

Categories

Resources