Ну, простыми словами:
Вы пытаетесь получить доступ к объекту, который не создан или в настоящее время не находится в памяти.
Итак, как это решить:
if (i == null) {
// Handle this
}
Поиск по имени означает, что некоторые фреймворки позволяют использовать FIndObjects с помощью строк, а код может выглядеть так: FindObject («ObjectName»);
Вы правы в TaskCompletionSource, это ключ к преобразованию EAP (асинхронный шаблон на основе событий) в задачу TPL.
Это описано здесь: https://docs.microsoft. com / en-us / dotnet / standard / parallel-programming / tpl-and-traditional-async-programming # разоблачение-complex-eap-operations-as-tasks
Вот упрощенная code:
public static class Extensions
{
public static Task<XDocument> GetRssDownloadTask(
this WebClient client, Uri rssFeedUri)
{
// task completion source is an object, which has some state.
// it gives out the task, which completes, when state turns "completed"
// or else it could be canceled or throw an exception
var tcs = new TaskCompletionSource<XDocument>();
// now we subscribe to completed event. depending on event result
// we set TaskCompletionSource state completed, canceled, or error
client.DownloadStringCompleted += (sender, e) =>
{
if(e.Cancelled)
{
tcs.SetCanceled();
}
else if(null != e.Error)
{
tcs.SetException(e.Error);
}
else
{
tcs.SetResult(XDocument.Parse(e.Result));
}
};
// now we start asyncronous operation
client.DownloadStringAsync(rssFeedUri);
// and return the underlying task immediately
return tcs.Task;
}
}
Теперь все, что вам нужно сделать, чтобы сделать цепочку этих операций, - это просто установить ваши продолжения (что на данный момент не очень удобно, а C # 5 ждет и async сильно поможет с этим)
Итак, этот код можно использовать следующим образом:
public static void Main()
{
var client = new WebClient();
client.GetRssDownloadTask(
new Uri("http://blogs.msdn.com/b/ericlippert/rss.aspx"))
.ContinueWith( t => {
ShowXmlInMyUI(t.Result); // show first result somewhere
// start a new task here if you want a chain sequence
});
// or start it here if you want to get some rss feeds simultaneously
// if we had await now, we would add
// async keyword to Main method defenition and then
XDocument feedEric = await client.GetRssDownloadTask(
new Uri("http://blogs.msdn.com/b/ericlippert/rss.aspx"));
XDocument feedJon = await client.GetRssDownloadTask(
new Uri("http://feeds.feedburner.com/JonSkeetCodingBlog?format=xml"));
// it's chaining - one task starts executing after
// another, but it is still asynchronous
}
У Джереми Ликнес есть заголовок блога Coroutines для асинхронных последовательных рабочих процессов с использованием Reactive Extensions (Rx) , которые могут вас заинтересовать. Вот вопрос, на который он пытается ответить:
. Концепция прост: часто мы хотим, чтобы асинхронный набор операций выполнялся последовательно. Возможно, вам нужно загрузить список из службы, затем загрузить выбранный элемент, а затем запустить анимацию. Это можно сделать либо путем цепочки завершенных событий, либо вложенных лямбда-выражений, но есть ли более чистый способ?
blockquote>