Skip to content

Instantly share code, notes, and snippets.

@bbrt3
Last active July 31, 2021 17:33
Show Gist options
  • Save bbrt3/803ace9a288d4edba4a07e7468bdc5a7 to your computer and use it in GitHub Desktop.
Save bbrt3/803ace9a288d4edba4a07e7468bdc5a7 to your computer and use it in GitHub Desktop.
Asynchronous Programming in C#
private async void Search_Click(object sender, RoutedEventArgs e)
{
...
// By using Task.Run we can execute code that is not asynchronous-friendly
// on different thread so it wont block our main UI for example.
await Task.Run(() =>
{
var lines = File.ReadAllLines(@"path");
var data = new List<StockPrices>();
foreach (var line in lines.Skip(1))...
// different thread that we need to communicate in
// that's where dispatcher comes in, it lets us communicate with our UI
Dispatcher.Invoke(() =>
{
Stocks.ItemSource = data.Where(price => price.Ticker == Ticker.Text);
});
});
...
}
// TAP (Task-based asynchronous pattern)
- best practice today
- based on Task, Task<T>, GetAwaiter()-implementing types
// EAP (Event-based asynchronous pattern)
- multithreading without the complexity
- MethodNameAsync (method)
- MethodNameCompleted (event)
- MethodNameAsyncCancel (method)
- mainly used before .NET 4
// APM (Asynchronous Programming Model)
- Async operations are implemented as two methods named:
BeginOperationName and EndOperationName
- FileStream used this model, but it was replaced with TAP
public void ConfigureServices(IServiceCollection services)
{
...
// default DbContext lifetime is Scoped!!!
services.AddDbContext<BookContext>(o => o.UseSqlServer(Configuration.GetConnectionString("BooksDBConnectionString")));
// that means that repository can't be a singleton
// must be the same scope or transient
// if it would be transient we would lose any state our repository might hold
// as with every new request new instance is created
// so we should use scoped lifetime for repository
services.AddScoped<IBookRepository, BookRepository>();
...
}
[ApiController]
[Route("api/books")]
public class BooksController : ControllerBase
{
private IBookRepository _repository;
public BooksController(IBookRepository repository)
{
_repository = repository;
}
[HttpGet]
public async Task<IActionResult> GetBooks()
{
var bookEntities = await _repository.GetBooksAsync();
return Ok(bookEntities);
}
[HttpGet]
[Route("{id}")]
public async Task<IActionResult> GetBook(Guid id)
{
var bookEntity = await _repository.GetBookAsync(id);
if (bookEntity == null)
{
return NotFound();
}
return Ok(bookEntity);
}
}
public interface IBookRepository
{
Task<IEnumerable<Book>> GetBooksAsync();
Task<Book> GetBookAsync(Guid id);
}
public class BookRepository : IBookRepository
{
private BookContext _context;
public BookRepository(BookContext context)
{
_context = context;
}
public async Task<Book> GetBookAsync(Guid id)
{
return await _context.Books.Include(b => b.Author).FirstOrDefaultAsync(b => b.Id == id);
}
public async Task<IEnumerable<Book>> GetBooksAsync()
{
return await _context.Books.Include(b => b.Author).ToListAsync();
}
}
public class BookRepository : IBookRepository, IDisposable
{
private BookContext _context;
private bool disposedValue;
public BookRepository(BookContext context)
{
_context = context;
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
_context.Dispose();
_context = null;
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
private void Search_Click(object sender, RoutedEventArgs e)
{
...
// TASK 1 - THREAD 1
var loadLinesTask = Task.Run(() =>
{
var lines = File.ReadAllLines(@"path");
return lines;
});
// TASK 2 (continuation of task 1) - THREAD 2
loadLinesTask.ContinueWith(t => {
// because last task has already ended
// we can read and use its result
// and continue with other stuff
var lines = t.Result
var data = new List<StockPrices>();
foreach (var line in lines.Skip(1))...
Dispatcher.Invoke(() =>
{
Stocks.ItemSource = data.Where(price => price.Ticker == Ticker.Text);
});
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment