单击“发送”按钮后,我的窗口冻结。它发送文件,然后它应该发布GUI,但它不会。看我的代码:
private void btn_send_Click(object sender, RoutedEventArgs e)
{
if (SBox.UploadFile("user", "service", 1, path.Text))
MessageBox.Show("Success");
else
MessageBox.Show("Fail, try again");
}
然后来自Sbox类的代码:
public static bool UploadFile(string user, string service, int orderId, string filepath)
{
DateTime now = DateTime.Now;
dbx = new DropboxClient(login_key);
string path = "/Files/" + user + "/" + service + "/order - " + orderId + "/received";
string fileName = now.Year + "" + now.ToString("MM") + "" + now.ToString("dd") + "" + Path.GetExtension(filepath);
Task upl = Upload(dbx, path, fileName, File.ReadAllBytes(filepath)); //send file
upl.Wait();
return true;
}
和任务代码:
static async Task Upload(DropboxClient dbx, string folder, string file, byte[] content)
{
using (var mem = new MemoryStream(content))
{
var updated = await dbx.Files.UploadAsync(
folder + "/" + file,
WriteMode.Overwrite.Instance,
body: mem);
Console.WriteLine("Saved {0}/{1} rev {2}", folder, file, updated.Rev);
}
}
正如我所说,文件发送到正确的文件夹,但GUI冻结。控制台应用程序运行良好,成功时写出输出。
答案 0 :(得分:1)
您正在Task.Wait()使用upl.Wait();
这会导致当前线程运行并等待任务完成后再继续。
修改强>
如果你想做的不仅仅是那个方法(在完成时执行其他操作),我总是使用Task.Run()
这样的任务:
Task.Run(() =>
{
Upload(...);
OnCompletion();
}
如果你想做UI的东西,记得在调度线程上调用它:
Task.Run(() =>
{
Upload(...);
Dispatcher.BeginInvoke(new Action(() => {
OnCompletion();
};
}
答案 1 :(得分:0)
我确实玩了一下并做了一些研究。这是我最后的工作代码 按钮:
import slick.codegen.SourceCodeGenerator
import slick.driver.{JdbcProfile, PostgresDriver}
import slick.jdbc.meta.MTable
import slick.model.Column
import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
object MySlickCodeGenerator {
val slickDriver = "slick.driver.PostgresDriver"
val jdbcDriver = "org.postgresql.Driver"
val url = "jdbc:postgresql://localhost:5432/dbname"
val outputFolder = "/path/to/project/src/test/scala"
val pkg = "my.package"
val user = "user"
val password = "password"
val driver: JdbcProfile = Class.forName(slickDriver + "$").getField("MODULE$").get(null).asInstanceOf[JdbcProfile]
val dbFactory = driver.api.Database
val db = dbFactory.forURL(url, driver = jdbcDriver, user = user, password = password, keepAliveConnection = true)
// The schema is generated using Liquibase, which creates these tables that I don't want to use
def excludedTables = Array("databasechangelog", "databasechangeloglock")
def tableFilter(table: MTable): Boolean = {
!excludedTables.contains(table.name.name) && schemaFilter(table.name.schema)
}
// There's also an 'audit' schema in the database, I don't want to use that one
def schemaFilter(schema: Option[String]): Boolean = {
schema match {
case Some("public") => true
case None => true
case _ => false
}
}
// Fetch data model
val modelAction = PostgresDriver.defaultTables
.map(_.filter(tableFilter))
.flatMap(PostgresDriver.createModelBuilder(_, ignoreInvalidDefaults = false).buildModel)
val modelFuture = db.run(modelAction)
// customize code generator
val codegenFuture = modelFuture.map(model => new SourceCodeGenerator(model) {
// add custom import for added data types
override def code = "import my.package.Java8DateTypes._" + "\n" + super.code
override def Table = new Table(_) {
table =>
// Use different factory and extractor functions for tables with > 22 columns
override def factory = if(columns.size == 1) TableClass.elementType else if(columns.size <= 22) s"${TableClass.elementType}.tupled" else s"${EntityType.name}.apply"
override def extractor = if(columns.size <= 22) s"${TableClass.elementType}.unapply" else s"${EntityType.name}.unapply"
override def EntityType = new EntityTypeDef {
override def code = {
val args = columns.map(c =>
c.default.map( v =>
s"${c.name}: ${c.exposedType} = $v"
).getOrElse(
s"${c.name}: ${c.exposedType}"
)
)
val callArgs = columns.map(c => s"${c.name}")
val types = columns.map(c => c.exposedType)
if(classEnabled){
val prns = (parents.take(1).map(" extends "+_) ++ parents.drop(1).map(" with "+_)).mkString("")
s"""case class $name(${args.mkString(", ")})$prns"""
} else {
s"""
/** Constructor for $name providing default values if available in the database schema. */
case class $name(${args.map(arg => {s"val $arg"}).mkString(", ")})
type ${name}List = ${compoundType(types)}
object $name {
def apply(hList: ${name}List): $name = new $name(${callArgs.zipWithIndex.map(pair => s"hList${tails(pair._2)}.head").mkString(", ")})
def unapply(row: $name) = Some(${compoundValue(callArgs.map(a => s"row.$a"))})
}
""".trim
}
}
}
override def PlainSqlMapper = new PlainSqlMapperDef {
override def code = {
val positional = compoundValue(columnsPositional.map(c => if (c.fakeNullable || c.model.nullable) s"<<?[${c.rawType}]" else s"<<[${c.rawType}]"))
val dependencies = columns.map(_.exposedType).distinct.zipWithIndex.map{ case (t,i) => s"""e$i: GR[$t]"""}.mkString(", ")
val rearranged = compoundValue(desiredColumnOrder.map(i => if(columns.size > 22) s"r($i)" else tuple(i)))
def result(args: String) = s"$factory($args)"
val body =
if(autoIncLastAsOption && columns.size > 1){
s"""
val r = $positional
import r._
${result(rearranged)} // putting AutoInc last
""".trim
} else {
result(positional)
}
s"""
implicit def $name(implicit $dependencies): GR[${TableClass.elementType}] = GR{
prs => import prs._
${indent(body)}
}
""".trim
}
}
override def TableClass = new TableClassDef {
override def star = {
val struct = compoundValue(columns.map(c=>if(c.fakeNullable)s"Rep.Some(${c.name})" else s"${c.name}"))
val rhs = s"$struct <> ($factory, $extractor)"
s"def * = $rhs"
}
}
def tails(n: Int) = {
List.fill(n)(".tail").mkString("")
}
// override column generator to add additional types
override def Column = new Column(_) {
override def rawType = {
typeMapper(model).getOrElse(super.rawType)
}
}
}
})
def typeMapper(column: Column): Option[String] = {
column.tpe match {
case "java.sql.Date" => Some("java.time.LocalDate")
case "java.sql.Timestamp" => Some("java.time.LocalDateTime")
case _ => None
}
}
def doCodeGen() = {
def generator = Await.result(codegenFuture, Duration.Inf)
generator.writeToFile(slickDriver, outputFolder, pkg, "Tables", "Tables.scala")
}
def main(args: Array[String]) {
doCodeGen()
db.close()
}
}
和SBox类中的方法:
private async void btn_send_Click(object sender, RoutedEventArgs e)
{
SBox sbox = new SBox();
progress.Text = "Uploading file, please wait...";
bool t = await sbox.UploadFromGUI("user", "service", 1, path.Text);
progress.Text = "";
if (t == true)
MessageBox.Show("Success!", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
else
MessageBox.Show("Failed", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}