You should probably use async
and await
. Basically, the two functions (and two buttons) have nothing to do with each other, assuming that you don't actively block the GUI.
As an example, you can make a simple UI with 4 controls (I made it in WPF). Two buttons, which each invoke an async method, and two text blocks, which will be updated after the async method.
The WPF code is quite simple. Notice the name of the click events.
<UniformGrid Columns="2">
<Button x:Name="UpdateSlow" Content="Wait 10 seconds" Click="UpdateSlow_Click" />
<Button x:Name="UpdateFast" Content="Wait 3 seconds" Click="UpdateFast_Click" />
<TextBlock x:Name="LongWaitTime" Text="Waiting for text" />
<TextBlock x:Name="ShortWaitTime" Text="Waiting for text" />
</UniformGrid>
And the code behind, which contains the click events.
private async void UpdateSlow_Click(object sender, RoutedEventArgs e)
{
await Task.Delay(10000);
LongWaitTime.Text = "I finished in 10 seconds";
}
private async void UpdateFast_Click(object sender, RoutedEventArgs e)
{
await Task.Delay(3000);
ShortWaitTime.Text = "I finished in 3 seconds";
}
If you click the "UpdateSlow" button, there will be a 10 seconds delay, before the "LongWaitTime" text block gets changed. In the mean time you can click the "UpdateFast" button, which will update the "ShortWaitTime" text block after just 3 seconds. Most likely finishing before the 10 seconds wait time is over (depending on when you click of course).
Hope that makes sense...
Modifying a text block:
I cannot figure out exactly what your goal is, which makes it difficult to come up with a really good solution. If it's just for the fun of it, the code below should work. However, I am unsure of any possible side effects of accessing the same string build from two different methods, so I wouldn't recommend this for production.
<UniformGrid Columns="1">
<Button x:Name="AddStar" Content="Add star to text" Click="AddStar_Click" />
<TextBlock x:Name="Dots" Text="." Margin="20 0" VerticalAlignment="Center" FontSize="24" />
</UniformGrid>
public MainWindow()
{
InitializeComponent();
PrintDots();
}
public async void PrintDots()
{
// This will run forever, printing a dot every 0.2 seconds, clearing the string, when it reaches 50 characters.
while (true)
{
_sb.Append(".");
await Task.Delay(200);
if (_sb.Length == 50) { _sb.Clear(); }
Dots.Text = _sb.ToString();
}
}
private void AddStar_Click(object sender, RoutedEventArgs e)
{
// On click a star (asterix) will be appended to the string
_sb.Append("*");
Dots.Text = _sb.ToString();
}
I decided to keep the string in a StringBuilder, as that should be a lot better for performance, as well as improving the readability by having an "Append" method.
A fair warning:
Normally async void
should only be used in user interfaces (e.g. on button click events). In most other cases it is not a good way of doing asynchronous programming. The program will have no way to track the method progress, once started. This could lead to all sorts of funky situations where you don't know which methods are done, and which aren't. Instead you should use async Task
which can be returned and awaited.