我有以下方法
array_filter($yourArrayToFilter, function($value) {
return (is_null($value))? false : true;
});
它将在WPF应用程序中使用,我希望能够通知UI读取进度。我必须举办一个简单的活动吗?就像是 OnProgress(new MyProgressEventHandler(recordcounter));我确信这样的方法会在执行时冻结UI,是否有更好的事情可以做,例如使用asyncronous方法仍然等待方法执行但是能够通知用户它正在做什么?
答案 0 :(得分:2)
you can pass in a IProgress<T>
and use it's Report(T)
method. If the object backing the interface is a Progress<T>
it will automaticly marsal the callback on the UI if the object was created on the UI thread.
//elsewhere
public class GetAllProgress
{
public GetAllProgress(int count, int total)
{
Count = count;
Total = total;
}
public Count {get;}
public Total {get;}
}
public List<VatRate> GetAll( string cnString, IProgress<GetAllProgress> progress )
{
List<VatRate> result = new List<VatRate>();
using (SqlConnection cn = new SqlConnection(cnString))
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandText = SQL_SELECT_COUNT;
//You don't need to do set CommandType to text, it is the default value.
cn.Open();
var totalCount = (int)cmd.ExecuteScalar();
progress.Report(new GetAllProgress(0, totalCount));
cmd.CommandText = SQL_SELECT;
using(SqlDataReader reader = cmd.ExecuteReader())
{
//reader.HasRows is unnecessary, if there are no rows reader.Read() will be false the first call
while (reader.Read())
{
VatRate vr = new VatRate();
vr.IDVatRate = reader["IDVatRate"] == System.DBNull.Value ? Guid.Empty : (Guid)reader["IDVatRate"];
vr.Percent = reader["Percent"].XxNullDecimal();
vr.Type = reader["Type"].XxNullString();
vr.VatRateDescription = reader["VatRateDescription"].XxNullString();
result.Add(vr);
progress.Report(new GetAllProgress(result.Count, TotalCount));
}
//I put reader in a using so you don't need to close it.
}
//You don't need to do cn.Close() inside a using
}
return result;
}
You can then call GetAll
on a background thread (just be sure to call new Progress<GetAllProgress>()
on the UI thread) or re-write the function to be async.
public async Task<List<VatRate>> GetAllAsync( string cnString, IProgress<GetAllProgress> progress )
{
List<VatRate> result = new List<VatRate>();
using (SqlConnection cn = new SqlConnection(cnString))
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandText = SQL_SELECT_COUNT;
//The .ConfigureAwait(false) makes it so it does not need to wait for the UI thread to become available to continue with the code.
await cn.OpenAsync().ConfigureAwait(false);
var totalCount = (int)await cmd.ExecuteScalarAsync().ConfigureAwait(false);
progress.Report(new GetAllProgress(0, totalCount));
cmd.CommandText = SQL_SELECT;
using(SqlDataReader reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false))
{
while (await reader.ReadAsync().ConfigureAwait(false))
{
VatRate vr = new VatRate();
vr.IDVatRate = reader["IDVatRate"] == System.DBNull.Value ? Guid.Empty : (Guid)reader["IDVatRate"];
vr.Percent = reader["Percent"].XxNullDecimal();
vr.Type = reader["Type"].XxNullString();
vr.VatRateDescription = reader["VatRateDescription"].XxNullString();
result.Add(vr);
progress.Report(new GetAllProgress(result.Count, TotalCount));
}
}
}
return result;
}
答案 1 :(得分:0)
在这里,我只为WPF添加一些部分。
在WPF中,您可以使用<ProgressBar>
,只需设置值即可显示进度。
<Grid>
<ProgressBar x:Name="progressBar" HorizontalAlignment="Left" Height="22" Margin="59,240,0,0" VerticalAlignment="Top" Width="383"/>
</Grid>
当您致电GetAllAsync
时,您实际上可以像下面一样轻松编写代码:
await GetAllAsync(new Progress<GetAllProgress>(progress=> { progressBar.Maximum = progress.Total; progressBar.Value = progress.Count; } ));
顺便说一下,最好使用MVVM模式并将你的ADO逻辑与UI分离,你可以看看这个article。