Asynchronní operace   zodpovězená otázka

C#

Mám v aplikaci (mimo jiné) implementovaný překladač, který zkrátka pošle uživatelem vložený text a vrátí jeho překlad. Funguje to ovšem (samozřejmě to funguje přes internet). Operace ověření a překladu ovšem zabere asi 2-3 sekundy, a proto bych to potřeboval posílat asynchronně.

Jaký typ operace si mám nastudovat? Dosud jsem se setkal s:

1)Backgroundworker

2)jiné vlákno (new Thread())

3)BeginInvoke() u delegáta

Přiznám se, že nevím, jaký je mezi nimi ve výsledku rozdíl? Jakou metodu mám tedy pro tento případ zvolit?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jakým způsobem stahujete data z Internetu? Pokud nepotřebujete nějaký extra dohled nad děním na síti a jde Vám pouze o výsledek, asi nejlepší bude použít WebClient z namespace System.Net, který poskytuje jako POST, tak GET blokující i asynchronní metody. Příkladem jedné takové je DownloadStringAsync, což je metoda, která stáhne zdrojový kód stránky z webu:

http://msdn.microsoft.com/en-us/library/...

Po dokončení stahování se vyvolá událost DownloadStringCompleted:

http://msdn.microsoft.com/en-us/library/... DownloadStringCompleted

http://msdn.microsoft.com/en-us/library/... DownloadStringCompletedEventArgs

Zde je krátká ilustrace použití:

  Sub Main()
    Using client = New WebClient()
      client.DownloadStringAsync(New Uri("http://www.example.org"))
      ' Navážeme na událost DownloadStringCompleted
      AddHandler client.DownloadStringCompleted,
        Sub(sender As Object, e As DownloadStringCompletedEventArgs)
          ' Ověříme, zda nedošlo ke zrušení nebo chybě
          If Not e.Cancelled AndAlso e.Error Is Nothing Then
            Console.WriteLine(e.Result)
          End If
          Console.WriteLine("Staženo.")
        End Sub
    End Using
    Console.ReadLine()
  End Sub

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Využívám Bing translator API od Microsoftu.

http://msdn.microsoft.com/en-us/library/...

Tady je jejich kód:

http://pastebin.com/6sEKfu5p

nahlásit spamnahlásit spam 0 odpovědětodpovědět

V tomto případě bych to volal nejspíše v System.Threading.Tasks.Task.

http://msdn.microsoft.com/en-us/library/...

Task.Factory.StartNew(
  Sub()
    For Each item In container.Translate.Execute("example", "cs", "en")
      ' Zpracování
    Next
  End Sub
)

Task za Vás vytvoří vlákno a spustí v něm předanou metodu. Můžete zapsat i něco jako Task.Factory.StartNew(...).ContinueWith a pokračovat další metodou, která se spustí po doběhnutí Tasku.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Děkuji a dá se u této metody zabránit tomu, aby v průběhu jednoho vlákna nemohl uživatel spustit další? Typicky, aby při spuštění neklikal na tlačítko víckrát a posílalo se to několikrát. Resp. zamezit vytvoření nového vlákna, pokud už jedno běží. Ještě jednou děkuji.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
Dim task As Task = Nothing
Sub Button_Click()
  ' OrElse task.IsCompleted
  If task Is Nothing OrElse task.Status = TaskStatus.RanToCompletion Then
    task = Task.Factory.StartNew(...)
  End If
End Sub

Můžete to udělat takhle, ověřováním reference a případně stavem Tasku. Tento postup je potřeba upravit pro případy, kdy Task skončí chybou (TaskStatus.Canceled, TaskStatus.Faulted), takže tu podmínku budete asi chtít trochu rozšířit a nebo můžete použít vlastnost IsCompleted, která jednoduše řekne, zda Task už doběhl (ať to dopadlo jakkoliv, resp. RanToCompletion, Cancelled nebo Faulted, takže to třeba nedá True pro zatím nespuštěný Task).

http://msdn.microsoft.com/en-us/library/...

Doporučuji tu vlastnost IsCompleted, ale uvedl jsem záměrně příklad s ověřováním stavu, aby bylo vidět, že těch stavů může být vícero a je třeba to brát v potaz.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback