FileIO.ReadTextAsync ocasionalmente se cuelga
Frecuentes
Visto 2,880 veces
2
Solo estoy experimentando con WinRT y una aplicación de demostración que estoy creando es una aplicación básica de estilo "bloc de notas" que carga/guarda en el almacenamiento local. Si bien estoy familiarizado con el adecuado async
enfoque para la creación de aplicaciones WinRT, mi aplicación de demostración está utilizando un síncrono Load
para mantener las cosas simples.
El problema es que cuando se hace una llamada a Load
, funciona 2 de cada 3 veces y el resto del tiempo la aplicación se cuelga en la llamada var result = await FileIO.ReadTextAsync(storageFile);
public class ContentStorage : IContentStorage
{
private const string FileName = "contents.txt";
public string Load()
{
return LoadAsync().Result;
}
public void Save(string content)
{
SaveAsync(content);
}
private static async Task<string> LoadAsync()
{
var storageFile = await LocalFolder.GetFileAsync(FileName);
var result = await FileIO.ReadTextAsync(storageFile);
return result;
}
private static async void SaveAsync(string content)
{
var storageFile = await LocalFolder.CreateFileAsync(FileName, CreationCollisionOption.ReplaceExisting);
FileIO.WriteTextAsync(storageFile, content);
}
private static StorageFolder LocalFolder
{
get { return ApplicationData.Current.LocalFolder; }
}
}
¿Estoy haciendo algo extraordinariamente estúpido aquí?
FWIW, experimenté cambiando Load
para simplemente bloquear explícitamente en cada paso y esto mejora el bloqueo a 1 en 20, pero todavía no entiendo por qué se bloquea en absoluto ...
public string Load()
{
var storageFile = LocalFolder.GetFileAsync(FileName).AsTask().Result;
var result = FileIO.ReadTextAsync(storageFile).AsTask().Result;
return result;
}
2 Respuestas
4
Si bien estoy familiarizado con el adecuado
async
enfoque para la creación de aplicaciones WinRT, mi aplicación de demostración está utilizando un síncronoLoad
para mantener las cosas simples.
Realmente no. Mezclar código síncrono con código asíncrono es extremadamente complejo. Es mucho más simple simplemente usar async
en todas partes.
Cuando un async
El método continúa ejecutándose después de esperar una tarea, volverá a su contexto original de forma predeterminada. (Cubro esto con más detalle en mi async
/await
blog). Algunos contextos (como los contextos de la interfaz de usuario) solo permiten un único subproceso; si ese hilo está bloqueado (por ejemplo, en Task.Result
), entonces el async
El método no puede ingresar a ese contexto para completar su ejecución. Esto provoca un interbloqueo.
Para más información acerca de reembolsos, pagos de impacto económico o pagos por adelantado del crédito tributario por hijos, visite las siguientes páginas:
- La
async
/await
Preguntas Frecuentes tiene muchos detalles sobre la captura de contexto y el resumen. - Stephen Toub en el blog del equipo paralelo tiene otra publicación en el blog ¡Espera, interfaz de usuario y puntos muertos! ¡Oh mi!, que explica en detalle esta situación particular de interbloqueo.
- Escribí una respuesta exhaustiva para este tipo de punto muerto en una publicación en el foro de MSDN.
Este interbloqueo es lo suficientemente famoso como para que Microsoft lo haya demostrado:
contestado el 23 de mayo de 12 a las 14:05
1
Tratar de usar ConfigureAwait(false
) con la operación await, puede ser ReadTextAsync
no es seguro para subprocesos, por lo que colgará el subproceso de la interfaz de usuario cuando finalice la espera y volverá al subproceso de la interfaz de usuario.
Respondido 15 Oct 12, 08:10
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c# windows-runtime or haz tu propia pregunta.
No está haciendo nada para garantizar que WriteTextAsync() se complete. Mala idea. - Hans Passant
Hans, omitiendo el hecho de que falta la palabra clave awaits frente a WriteTextAsync, lo que hace que el carga no funciona como se esperaba? - rodrigoelp