Last active
July 31, 2021 17:33
-
-
Save bbrt3/803ace9a288d4edba4a07e7468bdc5a7 to your computer and use it in GitHub Desktop.
Asynchronous Programming in C#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
}); | |
}); | |
... | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>(); | |
... | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[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); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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