Domanda

Sono abbastanza nuovo a Silverlight e sono rimasto molto sorpreso di vedere che solo il download di file asincrono può essere fatto. Beh, ho cercato di contrastare questo agire semplicemente impostando una bandiera e in attesa su di esso per cambiare .. Questo è il mio semplice codice

    void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        WebClient webClient = new WebClient();
        webClient.DownloadProgressChanged +=
            new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
        webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
        webClient.OpenReadAsync(new Uri("/trunk/internal/SilverLightInterface.ashx?xxid=XXX", UriKind.Relative));
        while (XmlStateStream == null) { }
        lblProgress.Content = "Done Loading";
    }
    void webClient_DownloadProgressChanged(object sender, 
        DownloadProgressChangedEventArgs e) {

        lblProgress.Content = "Downloading " + e.ProgressPercentage + "%";
    }
    volatile Stream XmlStateStream = null;
    void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
        if (e.Error != null)
        {
            lblProgress.Content = "Error: " + e.Error.Message;
            return;
        }
        XmlStateStream = e.Result;

    } 

Questo sta causando Firefox per congelare in realtà verso l'alto (il che è estremamente fastidioso quando sto facendo altre cose mentre in via di sviluppo) (a proposito, complimenti a firefox perché ho provato e Firefox congelato, ma non ho perso quello che stavo scrivendo qui dopo il ripristino)

Non capisco il motivo per cui il while(XmlStateStream==null){} sta causando un blocco su. C'è qualche attributo per serrature o volatili (diverso da quello che ho già) o sto nella parte sbagliata del ciclo di vita pagina Silverlight o qualcosa del genere?

Sono molto confusa sul motivo per cui questo non sta funzionando.

Inoltre, questo è Silverlight 3.0

È stato utile?

Soluzione

Molto probabilmente, questo codice è in esecuzione in thread dell'interfaccia utente che gestisce tutte le interazioni del browser Web con l'utente. Questo è il motivo per cui non troverete alcuna operazione di blocco - perché tutto ciò che blocca congelare l'interfaccia utente esattamente nello stesso modo in cui avete visto! Cosa c'è di più, se il thread dell'interfaccia utente gestisce anche reti IO (che è comune), allora ti deadlock qui perché l'operazione asincrona siete in attesa sulla non potrà mai finire.

Ho paura che vi resta che riscrivere il codice come una macchina a stati guidata da operazioni asincrone.

Altri suggerimenti

Mentre è necessario per ottenere con la natura asincrona delle cose in Silverlight è possibile utilizzare C # 3 sintassi per mantenere le cose un po 'più insieme: -

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    DownloadXmlStateStream();
}

void DownloadXmlStateStream()
{
    WebClient webClient = new WebClient();

    webClient.DownloadProgressChanged += (s, e) => {    
        lblProgress.Content = "Downloading " + e.ProgressPercentage + "%";
    }

    webClient.OpenReadCompleted += (s, e) => {
        if (e.Error != null)
        {
            lblProgress.Content = "Error: " + e.Error.Message;
        }
        else
        {
            XmlStateStream = e.Result;
            lblProgress.Content = "Done Loading";
        }           
    } 

    webClient.OpenReadAsync(new Uri("/trunk/internal/SilverLightInterface.ashx?xxid=XXX", UriKind.Relative));
}

È necessario utilizzare l'evento DownloadFileCompleted.

cancellare questo:

while (XmlStateStream == null) { }
lblProgress.Content = "Done Loading";

aggiungere questo:

webClient.DownloadFileCompleted +=
    new DownloadFileCompletedEventHandler(webClient_DownloadFileCompleted);

e questo:

void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventHandler) {
    lblProgress.Content = "Done Loading";
}

Se davvero necessario avere scaricano sincrono, è necessario "sondaggio" per il download essere completo meno spesso. Prova a chiamare System.Threading.Thread.Sleep() con un ritardo di 50-250ms all'interno del tuo ciclo busy-wait.

Anche se questo riduce l'utilizzo della CPU spreco di codice, è possibile che non risolverà il problema di interfaccia utente di risposta. Dipende se il filo che sta chiamando il vostro MainPage_Loaded è l'unico che può chiamare gli eventi di aggiornamento dell'interfaccia utente. Se questo è il caso, allora l'interfaccia utente semplicemente non può aggiornare fino a che restituisce gestore.

Con il blocco fino a quando il file viene scaricato, non sei solo bloccare il thread UI del vostro silverlight app -. Si sta anche bloccando il thread dell'interfaccia utente del browser, sembrerebbe

Tutto quello che vuole veramente fare (presumo) è smettere la vostra applicazione di fare qualsiasi cosa fino al completamento del download. Prova ad aggiungere questa riga a MainPage_Loaded:

LayoutRoot.IsHitTestVisible = false;

Rimuovere il blocco ciclo while e il messaggio completato (le ultime due righe).

In webClient_OpenReadCompleted, aggiungere:

LayoutRoot.IsHitTestVisible = true;
lblProgress.Content = "Done Loading.";

E tutto dovrebbe funzionare il mio modo di pensare che si desidera.

Ecco il codice completo:

   void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
            WebClient webClient = new WebClient();
            webClient.DownloadProgressChanged +=
                    new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
            webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
            webClient.OpenReadAsync(new Uri("/trunk/internal/SilverLightInterface.ashx?xxid=XXX", UriKind.Relative));
            LayoutRoot.IsHitTestVisible = false;
    }
    void webClient_DownloadProgressChanged(object sender, 
            DownloadProgressChangedEventArgs e) {

            lblProgress.Content = "Downloading " + e.ProgressPercentage + "%";
    }

    void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
            if (e.Error != null)
            {
                    lblProgress.Content = "Error: " + e.Error.Message;
                    return;
            }
            LayoutRoot.IsHitTestVisible = true;
            lblProgress.Content = "Done Loading.";

    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top