简体   繁体   中英

Passing variable to event listener with multible call

In a button event function, I have a multible links to download multible files. to dowload these files I have this code:

        for (int l = 0; l < itemLinks.Count(); l++)
        {
            string[] sourceParts = itemLinks[l].Split('/');
            string fileName = sourceParts[sourceParts.Count() - 1];
            WebClient client = new WebClient();
            client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
            client.OpenReadCompleted += client_OpenReadCompleted;
            client.OpenReadAsync(new Uri(itemLinks[l]));
        }

Here at the following function for OpenReadCompletedEventArgs I need to know which file's download is completed:

    async void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
        string pff = e.ToString();
        byte[] buffer = new byte[e.Result.Length];
        await e.Result.ReadAsync(buffer, 0, buffer.Length);

        using (IsolatedStorageFile storageFile =    
                   IsolatedStorageFile.GetUserStoreForApplication())
        {
            using (IsolatedStorageFileStream stream = storageFile
                             .OpenFile(FILE_NAME, FileMode.Create))
            {
                await stream.WriteAsync(buffer, 0, buffer.Length);
            }
        }

        //Also I need to do some stuff here with FILE_NAME
      }

How can I send FILE_NAME value to client_OpenReadCompleted?

I can not keep the value in a global variable since it will change in every call at the for statement, also I have tried to send the variable as += (sender, eventArgs) => But I have await in my code which force me to change button function as async

OpenReadAsync has an overload expecting a "userToken" parameter. It has been designed for this very purpose.

When calling OpenReadAsync , use this overload with your variable:

client.OpenReadAsync(new Uri(itemLinks[l]), fileName);

then, in the event handler, retrieve it:

void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    string fileName = (string)e.UserState;

    // ...
}

Since you're using await , a much cleaner solution is available if you use HttpClient instead of WebClient :

await Task.WhenAll(itemLinks.Select(DownloadAsync));

private static async Task DownloadAsync(string itemLink)
{
    string[] sourceParts = itemLinks[l].Split('/');
    string fileName = sourceParts[sourceParts.Count() - 1];
    using (var client = new HttpClient())
    using (var source = await client.GetStreamAsync(itemLink))
    using (IsolatedStorageFile storageFile = IsolatedStorageFile.GetUserStoreForApplication())
    using (IsolatedStorageFileStream stream = storageFile.OpenFile(FILE_NAME, FileMode.Create))
    {
        await source.CopyToAsync(stream);
    }

    ... // Use fileName
}

I'm not entirely sure whether CopyToAsync is available on WP8 (it might be part of Microsoft.Bcl.Async ). If it's not, you can remove the GetStreamAsync line and replace the CopyToAsync line with this:

var buffer = await client.GetBytes(itemLink);
await stream.WriteAsync(buffer, 0, buffer.Length);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM